常见的定义

  1. const b: boolean = false;
  2. const n: number = 1;
  3. const s: string = 'abc';
  4. const n: null = null;
  5. const u: undefined = undefined;
  6. // 声明变量空值 只能复制undefined或者null
  7. const v: void = undefined || null;
  8. const union: string | number = 7;
  9. // 当访问联合类型的属性或方法时 只能访问共有属性和方法
  10. union.toString() // toString 共有
  11. readonly id:number; // 只读属性 只有在创建的时候可以赋值

空值返回函数

  1. function func(): void {}

空值和undefined&null的区别是 void类型变量只能赋值undefined&null 但是声明为undefined&null的 可以和其他原始数据类型相互赋对应类型的值

任意值 any

  1. const s; // s是任意值 不受类型约束
  2. const s = 7; // 推断为number 受number约束

接口声明

  1. interface Person {
  2. name: string;
  3. age?: number; // 可选
  4. love: any; // 任意类型
  5. [propName: string]: string // 任意属性 如果用了任意属性 则其他成员属性必须是该任意属性类型的子类型
  6. // 此时任意属性类型是string, 所以name,age,love都应该为string或者undeined或者null
  7. [propName: string]: string | number | any // 这样就可以解决上面必须是它子类型的问题
  8. }

数组

  1. const arr: number[] = [1, 2, 3] // 元素类型为number的数组
  2. const arr: Array<number> = [1, 2, 3]; // 泛型表示跟上面一条相等
  3. // 接口表示数组也可以
  4. interface NumberArray {
  5. [index: number]: number
  6. }
  7. // 类数组处理
  8. function sum() {
  9. let args: number[] = arguments; // 报错 arguments 不是数组
  10. }
  11. // 可以用接口表示 也可以用内置定义 IArguments 实现也相同
  12. function sum() {
  13. const args: {
  14. [index: number]: any;
  15. length: number;
  16. callee: Function;
  17. }
  18. }

函数表达式

函数是javascript的一等公民

  1. // 函数声明
  2. function sum(x: number, y: number): number {
  3. return x + y;
  4. }
  5. // 函数表达式
  6. const mySum: (x: number, y: number) => number = function (x: number, y: number): number {
  7. return x + y;
  8. };
  9. // 用接口定义函数
  10. interface SearchFunc {
  11. (source: string, subString: string): boolean;
  12. }
  13. const mySearch: SearchFunc;
  14. mySearch = function(source: string, subString: string) {
  15. return source.search(subString) !== -1;
  16. }
  17. // 可选参数 可选参数后面不允许出现必须参数
  18. function func(name: string, age?: number)
  19. // 参数默认值
  20. function func(name: string = 'abc', age?: number)
  21. // es6的剩余参数 ...rest参数
  22. function push(array: any[], ...items: any[]) {
  23. array.push()...
  24. }
  25. push([], 1, 2, 3, 4)
  26. // 重载
  27. function reverse(x: number): number;
  28. function reverse(x: string): string;
  29. function reverse(x: number | string): number | string {
  30. if (typeof x === 'number') {
  31. return Number(x.toString().split('').reverse().join(''));
  32. } else if (typeof x === 'string') {
  33. return x.split('').reverse().join('');
  34. }
  35. }

类型断言(表达式)

欺骗typescript编译器 尽量避免 类型断言并不会实质修改变量类型 只是ts编译过程使用

  1. // 语法
  2. as 类型 // animal as Cat 类型降级 动物降级成猫
  3. <类型>值 // <Cat>animal 类型降级 动物降级成猫
  4. // animal as Fish
  5. interface Cat {
  6. name: string;
  7. run(): void;
  8. }
  9. interface Fish {
  10. name: string;
  11. swim(): void;
  12. }
  13. // 联合类型
  14. function isFish(animal: Cat | Fish) {
  15. if (typeof (animal as Fish).swim === 'function') {
  16. return true;
  17. }
  18. return false;
  19. }
  20. // 联合类型可以被断言为其中一个类型
  21. // 父类可以被断言为子类 继承
  22. // 任何类型都可以被断言为 any
  23. // any 可以被断言为任何类型
  24. // 若 A 兼容 B,那么 A 能够被断言为 B,B 也能被断言为 A 要使得 A 能够被断言为 B,只需要 A 兼容 B 或 B 兼容 A 即可
  25. // 要使得 A 能够被断言为 B,只需要 A 兼容 B 或 B 兼容 A 即可

双重断言

  1. // 任何类型都可以被断言为 any
  2. // any 可以被断言为任何类型
  3. interface Cat {
  4. run(): void;
  5. }
  6. interface Fish {
  7. swim(): void;
  8. }
  9. function testCat(cat: Cat) {
  10. return (cat as any as Fish); // 牛逼
  11. }

声明文件

  1. // 全局变量
  2. declare let jQuery: (selector: string) => any;
  3. declare var jQuery: (selector: string) => any;
  4. declare const jQuery: (selector: string) => any;
  5. // 全局方法
  6. declare function jQuery(selector: string): any;
  7. // 全局方法重载
  8. declare function jQuery(selector: string): any;
  9. declare function jQuery(domReadyCallback: () => any): any;
  10. // 全局类
  11. declare class Animal {
  12. name: string;
  13. constructor(name: string);
  14. sayHi(): string;
  15. }
  16. // 定义全局枚举
  17. declare enum Directions {
  18. Up,
  19. Down,
  20. Left,
  21. Right
  22. }
  23. // 定义全局变量对象
  24. declare namespace jQuery {
  25. function ajax(url: string, settings?: any): void;
  26. }
  27. declare namespace jQuery {
  28. function ajax(url: string, settings?: any): void;
  29. const version: number;
  30. class Event {
  31. blur(eventType: EventType): void
  32. }
  33. enum EventType {
  34. CustomClick
  35. }
  36. }
  37. // 命名空间嵌套
  38. declare namespace jQuery {
  39. function ajax(url: string, settings?: any): void;
  40. namespace fn {
  41. function extend(object: any): void;
  42. }
  43. }
  44. / ************ /
  45. jQuery.ajax('/api/get_something');
  46. jQuery.fn.extend({
  47. check: function() {
  48. return this.each(function() {
  49. this.checked = true;
  50. });
  51. }
  52. });
  53. // 单属性空间嵌套
  54. declare namespace jQuery.fn {
  55. function extend(object: any): void;
  56. }
  57. / ****** /
  58. jQuery.fn.extend({
  59. check: function() {
  60. return this.each(function() {
  61. this.checked = true;
  62. });
  63. }
  64. });
  65. // interface和type组合暴露两者
  66. // 声明
  67. interface AjaxSettings {
  68. method?: 'GET' | 'POST'
  69. data?: any;
  70. }
  71. declare namespace jQuery {
  72. function ajax(url: string, settings?: AjaxSettings): void;
  73. }
  74. // 使用
  75. let settings: AjaxSettings = {
  76. method: 'POST',
  77. data: {
  78. name: 'foo'
  79. }
  80. };
  81. jQuery.ajax('/api/post_something', settings);
  82. // 未避免命名冲突
  83. declare namespace jQuery {
  84. interface AjaxSettings {
  85. method?: 'GET' | 'POST'
  86. data?: any;
  87. }
  88. function ajax(url: string, settings?: AjaxSettings): void;
  89. }
  90. let settings: jQuery.AjaxSettings = {
  91. method: 'POST',
  92. data: {
  93. name: 'foo'
  94. }
  95. };
  96. jQuery.ajax('/api/post_something', settings);

类型别名

  1. // 类型别名
  2. type Name = string;
  3. type NameResolver = () => string;
  4. type NameOrResolver = Name | NameResolver;
  5. function getName(n: NameOrResolver): Name {
  6. if (typeof n === 'string') {
  7. return n;
  8. } else {
  9. return n();
  10. }
  11. }

字符串字面量类型

  1. // 限定了只能是这三类中的一类
  2. type EventNames = 'click' | 'scroll' | 'mousemove';
  3. function handleEvent(ele: Element, event: EventNames) {
  4. // do something
  5. }
  6. handleEvent(document.getElementById('hello'), 'scroll'); // 没问题
  7. handleEvent(document.getElementById('world'), 'dblclick'); // 报错,event 不能为 'dblclick'
  8. // index.ts(7,47): error TS2345: Argument of type '"dblclick"' is not assignable to parameter of type 'EventNames'.

枚举

  1. enum Days {Sun, Mon, Tue, Wed, Thu, Fri, Sat}; // 0,2,3,4,5,6...
  2. // 手动赋值 后续会在赋值后的值上累加
  3. enum Days {Sun = 7, Mon = 1, Tue, Wed, Thu=99, Fri, Sat}; // Tue = 2, Fri = 100

extends

  1. // TS的类型也支持条件运算,其语法与三目运算符相同,为T extends U ? X : Y
  2. type IsEqualType<A, B> = A extends B ? (B extends A ? true : false) : false;
  3. type NumberEqualsToString = IsEqualType<number, string>; // false
  4. type NumberEqualsToNumber = IsEqualType<number, number>; // true
  5. // redux
  6. export type StateFromReducersMapObject<M> = M extends ReducersMapObject
  7. ? { [P in keyof M]: M[P] extends Reducer<infer S, any> ? S : never }
  8. : never

infer 待推断类型

  1. // 如果T是继承 any的
  2. type ParamType<T> = T extends (param: infer P) => any ? P : T;
  3. type Unpacked<T> =
  4. T extends (infer U)[] ? U :
  5. T extends (...args: any[]) => infer U ? U :
  6. T extends Promise<infer U> ? U :
  7. T;
  8. // 1. T extends (infer U)[] = false, string 没有继承string[]
  9. // 2. T extends (...args: any[]) => infer U = false, string不是方法类型
  10. // 3. T extends Promise<infer U> = false, string不是Promise类型
  11. // 4. 返回T
  12. type T0 = Unpacked<string>; // string
  13. type T1 = Unpacked<string[]>; // string
  14. // 1. T extends (infer U)[] = false, string 没有继承string[]
  15. // 2. T extends (...args: any[]) => infer U = false, () => string 没有继承该方法类型
  16. // 3. T extends Promise<infer U> = false, string不是Promise类型
  17. // 4. 返回T
  18. type T2 = Unpacked<() => string>; // string
  19. type T3 = Unpacked<Promise<string>>; // string
  20. // 1. T extends (infer U)[] = true, T = Promise<string>, T extends Promise<string>[]
  21. // 2. 返回T
  22. type T4 = Unpacked<Promise<string>[]>; // Promise<string>
  23. type T5 = Unpacked<Unpacked<Promise<string>[]>>; // string

联合类型和extends条件推断

https://juejin.im/post/6844904066485583885

  1. // 条件类型匹配 不是简单的三元运算
  2. type Other = "a" | "b";
  3. type Merge<T> = T extends "x" ? T : Other; // T 等于匹配的类型,然后加上 Other 联合类型一起返回
  4. type Values = Merge<"x" | "y">;
  5. // 得到 type Values = "x" | "a" | "b";
  6. type Other = "a" | "b";
  7. type Merge<T> = T extends "x" ? Other : T; // T 等于除匹配类型的额外所有类型(官方叫候选类型)
  8. type Values = Merge<"x" | "y">;
  9. // 得到 type Values = "a" | "b" | 'y';
  10. // 实际应用
  11. type MakesSense = never extends never ? 'yes' : 'no' // Resolves to 'yes'
  12. // never = 空联合类型 运行 ... extends never将无返回结果 所以 ExtendsNever<never> = never
  13. type ExtendsNever<T> = T extends never ? 'yes' : 'no'
  14. // [T] [never]已经切换比较的类型 所以 ExtendsNever<never> = 'yes'
  15. type ExtendsNever<T> = [T] extends [never] ? 'yes' : 'no'
  16. type MakesSenseToo = ExtendsNever<{}> // Resolves to 'no'
  17. type Huh = ExtendsNever<never> // is yes

新奇语法

  1. // 相当于 user && user.userinfo && user.userinfo.username
  2. const name: string = user?.userinfo?.username
  3. // user一定存在 userinfo一定存在 的语法表示
  4. const name: string = user!.userinfo!.username

infer关键字

  1. export const tuple = <T extends string[]>(...args: T) => args;
  2. // eslint-disable-next-line import/prefer-default-export
  3. export const PresetColorTypes = tuple(
  4. 'pink',
  5. 'red',
  6. 'yellow',
  7. );
  8. // T extends xx T属于xx类型吗 判断语句 如果是 E是待推断类型 如果是E[]
  9. // 下面例子中T 是['pink', 'red', 'yellow'] 所以里面的元素类型为 'pink' | 'red' | 'yellow' 所以E='pink' | 'red' | 'yellow'
  10. export type ElementOf<T> = T extends (infer E)[] ? E : T extends readonly (infer F)[] ? F : never;
  11. // 'pink' | 'red' | 'yellow'
  12. export type PresetColorType = ElementOf<typeof PresetColorTypes>;