Open Hibop opened 4 years ago
基础类型 布尔值 boolean 数字 number 字符串 string 数组 let list: number[] = [1, 2, 3]; let (number | string)[] = [1,2, '3'] 元组(tuple) let x: [string, number] 枚举 enum Color {Red, Green, Blue}; let c: Color = Color.Green; any void null undefined 内置对象类型 Boolean、Error、Date、RegExp Document、HTMLElement、Event、NodeList 高级用法 类型断言: <类型>值 OR 值 as 类型 类型别名 type TypeAlise = string 泛型: 相当于类型变量 接口: interface 注解: declare
基础类型
高级用法
// ➖➖➖➖➖➖➖➖➖布尔➖➖➖➖➖➖➖➖➖ // 布尔值 let isDone: boolean = false; // 事实上 `new Boolean()` 返回的是一个 `Boolean` 对象 let createdByNewBoolean: Boolean = new Boolean(1); //(直接调用 `Boolean` 也可以返回一个 `boolean` 类型) let createdByBoolean: boolean = Boolean(1); // 易错, Mark 大写和小写boolean区别 // ➖➖➖➖➖➖➖➖➖数值➖➖➖➖➖➖➖➖➖ // 数值 let decLiteral: number = 6; let hexLiteral: number = 0xf00d; // ES6 中的二进制表示法 let binaryLiteral: number = 0b1010; // ES6 中的八进制表示法 let octalLiteral: number = 0o744; let notANumber: number = NaN; let infinityNumber: number = Infinity; // ➖➖➖➖➖➖➖➖➖字符串➖➖➖➖➖➖➖➖➖ let myName: string = 'Tom'; // ➖➖➖➖➖➖➖➖➖空值➖➖➖➖➖➖➖➖➖ // 没有返回值的函数为void function alertName(): void { alert('My name is Tom'); } // 声明一个 void 类型的只能将它赋值为 undefined 和 null let unusable: void = undefined; // ➖➖➖➖➖➖➖➖➖Null 和 Undefined➖➖➖➖➖➖➖➖➖ // undefined 类型的变量只能被赋值为 undefined,null 类型的变量只能被赋值为 null let u: undefined = undefined; let n: null = null; // ➖➖➖➖➖➖➖➖➖ any ➖➖➖➖➖➖➖➖➖ // 顾名思义,可以被任何值赋值 let anyThing1: any = 'hello'; let anyThing2: any = 888; let anyThing3: any = true; let anyThing4: any = null; let anyThing5: any = undefined; // 变量如果在声明的时候,未指定其类型,那么它会被识别为任意值类型: let any; any = true; // ➖➖➖➖➖➖➖➖➖ 类型推论 Type Inference ➖➖➖➖➖➖➖➖➖ // 如果没有明确的指定类型,那么 TypeScript 会依照类型推论(Type Inference)的规则推断出一个类型。 let myFavoriteNumber = 'seven'; // 等价于 let myFavoriteNumber: string = 'seven'; // 错误写法 let typeInferenceString = 'seven'; typeInferenceString = 'nine'; // OK // typeInferenceString = 7; // Error // ➖➖➖➖➖➖➖➖➖ 联合类型 Union Types ➖➖➖➖➖➖➖➖➖ // 联合类型(Union Types)表示取值可以为多种类型中的一种。 // 当你允许某个变量被赋值多种类型的时候,使用联合类型,管道符进行连接 let unionTypeStringOrType: string | number; unionTypeStringOrType = 'seven'; unionTypeStringOrType = 7; // 也可用于方法的参数定义, 都有toString方法,访问 string 和 number 的共有属性是没问题的 function getString(something: string | number): string { return something.toString(); } ////错误写法 // function getLength(something: string | number): number { // return something.length; // number 不存在length属相 // } // ➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖ // | **接口类型 interface (对象的类型) // ➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖ // 赋值的时候,变量的形状必须和接口的形状保持一致(不能多也不能少,类型还必须一致) // 接口的作用就是为这些类型命名 // 和为你的代码或第三方代码定义契约。 interface Person { name: string; age: number; } let tom: Person = { name: 'Tom', age: 25 }; interface IUserInfo{ age: any;//定义一个任何变量的 age. userName: string;//定义一个 username. } function getUserInfo(user: IUserInfo): string { return user.age + "======" + user.userName; } // ➖➖➖➖➖➖➖➖➖可选属性// ➖➖➖➖➖➖➖➖➖ interface Person1 { name: string; age?: number; // 表示这个属性可有可无 } let tom1: Person1 = { name: 'Tom' }; // ➖➖➖➖➖➖➖➖➖任意属性// ➖➖➖➖➖➖➖➖➖ //希望一个接口允许有任意的属性,可以使用如下方式:旦定义了任意属性,那么确定属性和可选属性的类型都必须是它的类型的子集 interface Person2 { name: string; age?: number; [propName: string]: any; } let tom2: Person2 = { name: 'Tom', gender: 'male' // 可以加其他的属性 }; // ➖➖➖➖➖➖➖➖➖只读属性// ➖➖➖➖➖➖➖➖➖ interface Person3 { readonly id: number; // name: string; age?: number; [propName: string]: any; } let tom3: Person3 = { id: 89757, // 只读 name: 'Tom', gender: 'male' }; // 错误写法 // 一旦定义了任意属性,那么确定属性和可选属性的类型都必须是它的类型的子集 // interface PersonErr { // name: string; // age?: number; // [propName: string]: string; // } // let tomerr: PersonErr = { // name: 'Tom', // age: 25, // gender: 'male' // ❌ // }; // 上例中,任意属性的值允许是 string,但是可选属性 age 的值却是 number,number 不是 string 的子属性,所以报错了。 // ➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖ // | **数组类型 Array // ➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖ let fibonacci1: number[] = [1, 1, 2, 3, 5]; let fibonacci2: Array<number> = [1, 1, 2, 3, 5]; // ➖➖➖➖➖➖➖➖➖用接口表示数组➖➖➖➖➖➖➖➖➖ interface NumberArray { [index: number]: number; } let fibonacci3: NumberArray = [1, 1, 2, 3, 5]; // ➖➖➖➖➖➖➖➖➖any 在数组中的应用➖➖➖➖➖➖➖➖➖ let list: any[] = ['Xcat Liu', 25, { website: 'http://xcatliu.com' }]; // ➖➖➖➖➖➖➖➖➖类数组➖➖➖➖➖➖➖➖➖ function arguments() { let args: IArguments = arguments; } // ➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖ // | **函数类型: 入参和返回类型必须 // ➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖➖ // 需要把输入和输出都考虑到 function sum(x: number, y: number): number { return x + y; } // ➖➖➖➖➖➖➖➖➖函数表达式➖➖➖➖➖➖➖➖➖ let mySum = function (x: number, y: number): number { return x + y; }; // 不要混淆了 TypeScript 中的 => 和 ES6 中的 => let mySum2: (x: number, y: number) => number = function (x: number, y: number): number { return x + y; }; // ➖➖➖➖➖➖➖➖➖接口定义函数的形状➖➖➖➖➖➖➖➖➖ interface SearchFunc { (source: string, subString: string): boolean; } let mySearch: SearchFunc; mySearch = function (source, subString) { return source.search(subString) !== -1; } // ➖➖➖➖➖➖➖➖➖可选参数➖➖➖➖➖➖➖➖➖ function buildName(firstName: string, lastName?: string) { if (lastName) { return firstName + ' ' + lastName; } else { return firstName; } } let tomcat = buildName('Tom', 'Cat'); let Tim = buildName('Tim'); // ➖➖➖➖➖➖➖➖➖参数默认值➖➖➖➖➖➖➖➖➖ function buildNameDefault(firstName: string, lastName: string = 'Cat') { return firstName + ' ' + lastName; } // ➖➖➖➖➖➖➖➖➖剩余参数➖➖➖➖➖➖➖➖➖ // rest 参数只能是最后一个参数,关于 rest 参数,是一个数组 function push(array: any[], ...items: any[]) { items.forEach(function (item) { array.push(item); }); } let a = []; push(a, 1, 2, 3); //// 错误栗子 // 在Ts中 输入多余的(或者少于要求的)参数,是不被允许的: // function sumErr(x: number, y: number): number { // return x + y; // } // sumErr(1, 2, 3); // ❌ // sumErr(1); // ❌ //// 可选参数后面不允许再出现必须参数了: // function genateName(firstName?: string, lastName: string) { // if (firstName) { // return firstName + ' ' + lastName; // } else { // return lastName; // } // } // let tomCat = genateName('Tom', 'Cat'); // let jim = genateName(undefined, 'Jim'); // ➖➖➖➖➖➖➖➖类型断言➖➖➖➖➖➖➖➖➖ // 可以使用类型断言,将 something 断言成 string function getLength2(something: string | number): number { if ((<string>something).length) { return (<string>something).length; } else { return something.toString().length; } } // 只能访问此联合类型的所有类型里共有的属性或方法 // function getLength3(something: string | number): number { // ❌ // return something.length; // } // ➖➖➖➖➖➖➖➖类型别名 alise➖➖➖➖➖➖➖➖➖ // 使用 type 创建类型别名,类型别名常用于联合类型 type Name = string; type NameResolver = () => string; // good use type NameOrResolver = Name | NameResolver; // good use function getName(n: NameOrResolver): Name { if (typeof n === 'string') { return n; } else { return n(); } } // ➖➖➖➖➖➖➖➖枚举 enum ➖➖➖➖➖➖➖➖➖ // 枚举(Enum)类型用于取值被限定在一定范围内的场景,比如一周只能有七天 // 枚举就是枚举值到枚举名进行反向映射 // enum Days { Sun, Mon, Tue, Wed, Thu, Fri, Sat } ==> Days // { // "0":"Sun","1":"Mon","2":"Tue","3":"Wed","4":"Thu","5":"Fri","6":"Sat", // "Sun":0,"Mon":1,"Tue":2,"Wed":3,"Thu":4,"Fri":5,"Sat":6 // } enum Days { Sun, Mon, Tue, Wed, Thu, Fri, Sat }; console.log(Days["Sun"]); // 0 console.log(Days[0]); // 'Sun' enum Days2 { Sun = 7, Mon = 1, Tue, Wed, Thu, Fri, Sat }; console.log(Days2["Sun"]); // 7 // ➖➖➖➖➖➖➖➖泛型 Generics➖➖➖➖➖➖➖➖➖ // 泛型就是解决 类 接口 方法的复用性、以及对不特定数据类型的支持 // 泛型解决编译期间不确定类型,运行时确定类型 // 只能返回string类型的数据 function getData(value: string): string { return value; } //同时返回 string类型 和number类型 (代码冗余) function getData1(value: string): string { return value; } function getData2(value: number): number { return value; } // >>>>>>>>>> 使用泛型后就可以解决这个问题 // T表示泛型,具体什么类型是调用这个方法的时候决定的 // 表示参数是什么类型就返回什么类型~~~ function getDataGenerics<T>(value: T): T { return value; } getDataGenerics<number>(123); getDataGenerics<string>('1214231'); // 定义接口 interface ConfigFn { <T>(value: T): T; } var getDatagenr: ConfigFn = function (value) { return value; } getDatagenr<string>('张三'); getDatagenr<number>(1243); //错误 // ➖➖➖➖➖➖➖➖类型声明 declare 注解➖➖➖➖➖➖➖➖➖ // 可以通过 declare 关键字,来告诉 TypeScript,你正在试图表述一个其他地方已经存在的代码(如:写在 JavaScript、CoffeeScript 或者是像浏览器和 Node.js 运行环境里的代码): // .d.ts declare var React: any; declare var Vue: any; // ➖➖➖➖➖➖➖➖类的新保留字 public private protected➖➖➖➖➖➖➖➖➖ // public 修饰的属性或方法是公有的,可以在任何地方被访问到,默认所有的属性和方法都是 public 的 // private 修饰的属性或方法是私有的,不能在声明它的类的外部访问 // protected 修饰的属性或方法是受保护的,它和 private 类似,区别是它在子类中也是允许被访问 // ➖➖➖➖➖➖➖➖➖类➖➖➖➖➖➖➖➖➖ interface Animal { name: string } class Animal { constructor(name) { this.name = name; } sayHi() { return `My name is ${this.name}`; } } let ani = new Animal('Jack'); console.log(ani.sayHi()); // My name is Jack // ➖➖➖➖➖➖➖➖➖继承➖➖➖➖➖➖➖➖➖ class Cat extends Animal { constructor(name) { super(name); // 调用父类的 constructor(name) console.log(this.name); } sayHi() { return 'Meow, ' + super.sayHi(); // 调用父类的 sayHi() } } let c = new Cat('Tom'); // Tom console.log(c.sayHi()); // Meow, My name is Tom // ➖➖➖➖➖➖➖➖➖存储器➖➖➖➖➖➖➖➖➖ class AnimalGetSet { constructor(name) { this.name = name; } get name() { return 'Jack'; } set name(value) { console.log('setter: ' + value); this.name = value; } } let aGs = new AnimalGetSet('Kitty'); // setter: Kitty aGs.name = 'Tom'; // setter: Tom console.log(aGs.name); // Jack //➖➖➖➖➖➖➖➖➖静态方法➖➖➖➖➖➖➖➖➖ class AnimalStatic { static isAnimal(a) { return a instanceof Animal; } } let aSta = new AnimalStatic(); AnimalStatic.isAnimal(aSta); // true // 只能通过类名调用 // aSta.isAnimal(aSta); // TypeError: a.isAnimal is not a function ❌ // ➖➖➖➖➖➖➖➖➖抽象类➖➖➖➖➖➖➖➖➖ abstract class AnimalAbstract { abstract makeSound(): void move(): void { console.log('roaming the earch...') } } // 子类必须实现抽象类的抽象方法 // ➖➖➖➖➖➖➖➖➖implements➖➖➖➖➖➖➖➖➖ interface Point { x: number; y: number; } class MyPoint implements Point { x: number; y: number; // Same as Point }
直接使用
vue-class-components
vue-next/blob/master/packages/reactivity/src/reactive.ts
一、Why Ts
二、Ts历史、编译原理、生态环境 【略】
三、 类型keywords
四、talk is cheap, show me the code
五、vue中使用ts (Vue2.5 + )
直接使用
vue-class-components
六、欣赏一段vue3.0 pre-alpha源码
vue-next/blob/master/packages/reactivity/src/reactive.ts