详细

TypeScript知识点

定义

TypeScript 是由微软开发的自由和开源的编程语言, 是JavaScript 的一个超集,支持 ECMAScript 6 标准。其设计目标是开发大型应用,它可以编译成纯 JavaScript,编译出来的 JavaScript 可以运行在任何浏览器上。

复杂的类型声明示例

常用知识点

  • 修饰符

    • public 在TypeScript里,成员都默认为 public,我们可以自由的访问程序里定义的成员
    • private 当成员被标记成 private时,它就不能在声明它的类的外部访问
    • protected 和private类似, 但是protected成员在派生类中仍然可以访问
  • 常用类型 stringbooleannumbernumber[]、、、、

  • type和interface区别

    • 相同点
      • 类型:对象、函数两者都适用
      • 都能通过extends进行扩展
    • 不同点
      • type能够声明别名而interface不行,type 可以用于基础类型、联合类型、元组。
      • 同名合并:interface 支持,type 不支持。
      interface User {
      name: string
      age: number
      }
      interface User {
      sex: string
      }
      /*
      User 接口为 {
      name: string
      age: number
      sex: string
      }
      */
      • 计算属性:type 支持, interface 不支持。
      let div = document.createElement('div');
      type B = typeof div
  • 用法概览1

// 布尔类型
let isCookie:boolean = true
// 数值类型
let myMoney:number = 12
// 字符串类型
let name:string = '徐小夕'
// 数组类型, 有两种表示方式,第一种可以在元素类型后面接上[],表示由此类型元素组成的一个数组
let arr:number[] = [1,2,2]
// 数组类型, 使用数组泛型
let arr:Array<number> = [1,2,2]
// 元组类型, 允许表示一个已知元素数量和类型的数组,各元素的类型不必相同
let xi: [string, number];
// 初始化xi
xi = ['xu', 10]; // 正确
xi = [11, 'xu']; // 错误
// 枚举类型, 可以为一组数值赋予友好的名字
enum ActionType { doing, done, fail }
let action:ActionType = ActionType.done // 1
// any, 表示任意类型, 可以绕过类型检查器对这些值进行检查
let color:any = 1
color = 'red'
// void类型, 当一个函数没有返回值时,通常会设置其返回值类型是 void
function getName(): void {
console.log("This is my name");
}
// object类型, 表示非原始类型,也就是除number,string,boolean,symbol,null或undefined之外的类型
let a:object;
a = {props: 1}
  • 用法概览2
// 类型断言- as or <>
// interface用于对象
interface App {
name: string;
color?: number;
[propName: string]: any;
}
// interface用于函数
interface MyFunc {
(value:string, type: number): boolean;
}
// interface用于类
interface TickInterface {
tick();
}
class DigitalClock implements TickInterface {
constructor(h: number, m: number) { }
tick() {
console.log("xu xu");
}
}
// 抽象类做为其它派生类的基类使用。它们一般不会直接被实例化。不同于接口,抽象类可以包含成员的实现细节。abstract关键字是用于定义抽象类和在抽象类内部定义抽象方法。
abstract class MyAbstract {
constructor(public name: string) {}
say(): void {
console.log('say name: ' + this.name);
}
abstract sayBye(): void; // 必须在派生类中实现
}
class AccountingMyAbstract extends MyAbstract {
constructor() {
super('test'); // 在派生类的构造函数中必须调用 super()
}
sayBye(): void {
console.log('test1');
}
getOther(): void {
console.log('test2');
}
}
let department: MyAbstract; // 允许创建一个对抽象类型的引用
department = new MyAbstract(); // 错误: 不能创建一个抽象类的实例
department = new AccountingMyAbstract(); // 允许对一个抽象子类进行实例化和赋值
department.say();
department.sayBye();
department.getOther(); // 错误: 方法在声明的抽象类中不存在
// 函数,在参数名旁使用 ?实现可选参数的功能,可选参数必须跟在必选参数后面
function createName(firstName: string, lastName?: string) {
if (lastName)
return firstName + " " + lastName;
else
return firstName;
}
/** 泛型 */
// 泛型-函数中直接使用
function iSay<T>(arg: T): T { // 整体使用泛型
return arg;
}
let come = iSay<number>(123);
function iSay<T>(arg: T[]): T[] { // 局部使用泛型
console.log(arg.length)
return arg;
}
// 泛型-函数中定义使用
interface SayLove {
<T>(arg: T): T
}
interface SayLoveArg<T> { // 把泛型参数当作整个接口的一个参数
(arg: T): T
}
let mySay1:SayLove = iSay
let mySay2:SayLoveArg<number> = iSay
// 泛型-类中直接使用
class MyNumber<T> {
year: T;
compute: (x: T, y: T) => T;
}
let myGenericNumber = new MyNumber<number>();
// 泛型-类中定义使用-类似类型别名
interface NumberControl {
length: number
}
class MyObject<T extends NumberControl>(arg: T):T {
console.log(arg.length)
return arg
}
// 交叉类型
function extend<T, U>(first: T, second: U): T & U {
let result = {} as T & U; // <T & U>{}
for (let id in first) {
(<any>result)[id] = (<any>first)[id];
}
for (let id in second) {
if (!result.hasOwnProperty(id)) {
(<any>result)[id] = (<any>second)[id];
}
}
return result;
}
// 联合类型
let name: string | number = 'test';
// 多态的 this类型
class MyCalculator {
public constructor(number = 0) { }
public add(n: number): this {
this.value += n;
return this;
}
public multiply(n: number): this {
this.value *= n;
return this;
}
// ... 其他操作 ...
}
// 索引类型查询操作符
interface Animal {
cat: string;
dog: string;
}
let AnimalProps: keyof Animal; // 'cat' | 'dog'
// 索引访问操作符
interface TestInterface {
a: string,
b: number,
c: boolean,
d: symbol,
e: null,
f: undefined,
g: never
}
type MyType = TestInterface[keyof TestInterface]; // 通过[]索引类型访问操作符, 我们就能得到某个索引的类型
// 命名空间-主要作用是用来组织代码,以便于在记录它们类型的同时还不用担心与其它对象产生命名冲突。
declare namespace D3 {
export interface Selectors {
select: {
(selector: string): Selection;
(element: EventTarget): Selection;
};
}
export interface Event {
x: number;
y: number;
}
export interface Base extends Selectors {
event: Event;
}
}
declare var d3: D3.Base;
// 使用第三方类库
npm install --save lodash @types/lodash
import * as _ from "lodash"; // 在代码中使用
_.padStart("Hello world!", 2, " ");
// 声明文件-使用未经声明的全局函数或者变量, typescript会报错, 可以添加xxx.d.ts文件, 并在里面声明所需变量, ts会自动检索到该文件并进行解析。
// global.d.ts
declare var name: string;// 1. 声明全局变量
declare function say(name: string): void;// 2. 全局函数
declare namespace myObj {// 3. 带属性的对象
function say(s: string): string;
let money: number;
}
interface Animal {// 4. 可重用的接口
kind: string;
age: number;
weight?: number;
}
declare function findAnmiate(animal:Animal):void;

常见DEMO

/** 一、interface和type有什么区别 */
// ****相同点****
// 1. 都能声明对象
// 2. 都能通过extends进行扩展
// 通过interface声明对象结构
interface A {
a: string;
}
// interface扩展另一个interface
interface AA extends A {
b: number;
}
// 通过type声明对象结构
type B = {
a: string;
};
// type扩展另一个type
type BB = B & { b: number };
// type和interface还能相互继承
type B = {
a: string;
};
interface C extends B {
b: number;
}
// ****不同点****
// 1. type能够声明别名而interface不行
// 2. 同名合并:interface 支持,type 不支持。
// 3. 计算属性,type 支持, interface 不支持。
type isNumberOrBool = number | boolean;
let a: isNumberOrBool = 1;
a = true;
// Bar { a, b, c }
interface Bar {
a: string
b: number
}
interface Bar {
c: string
}
type Keys = "firstname" | "surname";
type DudeType = {
[key in Keys]: string
}
/** 二、函数参数是对象时,会对对象字面量做额外的属性检查,但却不会对对象引用做检查处理 */
interface O {
a: string;
b: number;
}
function fn(o: O) {}
const o = { a: "a", b: 1, c: 3 };
// 下面一行能通过ts检查
fn(o);
// 下面一行不通过, 提示'c' does not exist in type 'O'
fn({ a: "a", b: 1, c: 3 });
/** 三、TypeScript的类型兼容性是基于结构的而非名义的 */
interface Named {
name: string;
}
class Person {
name: string;
}
let p: Named;
// OK, because of structural typing
p = new Person();
/** 四、模块,namespace和declare声明文件三者导入导出的区别 */
// 模块通过import/export去导入
// namespace和declare声明则是通过三斜线指令/// <reference path="..." />的方式去导入的
/** 五、传递过程中导致this丢失,指向全局,但是并没有收到报错 */
const fn = o.do;
// 报错,提示:The 'this' context of type 'void' is not assignable to method's 'this' of type 'O'
fn();

常见问题

Q: vscode中直接运行typescript需要安装
A: npm install -D tslib @types/node
npm install -g typescript ts-node