为什么使用 ts 
提供类型检查,减少错误 
更友好的代码提示 
增强代码可读性和可维护性 
更好的代码重构 
更好的代码组织和管理 
JS 的超集,扩展新功能 
 
转换 .ts 文件并不被浏览器所识别,运行不了。
所以需要转换为 .js 文件才能被浏览器所识别并运行。
我们可以安装 typescript,使用它提供的 tsc 来编译 .ts 文件。
安装:npm i -g typescript
转换:tsc xx.ts
不过,重新修改文件后需要重新运行转换命令。
如果想修改后自动进行装换,那么需要使用下面的命令。
自动监听的转换命令:tsc xx.ts -w
.ts 文件设置全局或局部环境 .ts 文件默认是全局环境的。也就是说,我们现在有两个文件,一个 a.ts,一个 b.ts。
a.ts 中定义了一个变量 a,let a = 1,在 b.ts 中输出变量 a,console.log(a)。
上面的代码不是不有警告的,b.ts 能够知道全局环境中有定义的 a 变量。
这样就不好了,我们希望 b.ts 只知道自己定义的 a 变量,而不应该知道全局环境中定义的 a 变量。
解决办法: 只要文件使用模块化操作,那么该文件就会变为局部环境。
方法: 在每个文件末尾添加 export {},这样 a.ts、b.ts 就变成了一个个独立的模块,b.ts 就只能使用自己定义的 a 变量了。
生成 tsconfig.json 文件 命令:tsc --init
联合类型 多个类型,只有符合其中的一个条件即可。
类型之间进行或操作。
let  a : string  | number  = '1' a = 1  type  A = { name : string  }type  B = { age : number  }let  person1 : A | B = { name : 'zhangsan'  }
交叉类型 多个类型,必须符合所有条件。
类型之间进行与操作。
type  A = { name : string  }type  B = { age : number  }let  person1 : A & B = { name : 'zhangsan' , age : 18  }
never 表示永远不会出现的值的类型。
很少用,一般是程序自动推断出来的。
let  a : string  & number  = 1  
也可以手动定义。
function  foo (n: 1  | 2  | 3  ) {    switch  (n) {         case  1 :             break          case  2 :              break          case  3 :             break          default :              let  m : never  = n             break      } } 
any 表示任意类型,任何类型都可以赋值给 any 类型。
any 使用时,TS 不进行检测。
unknown 表示 any 类型对应的安全类型。
unknow 使用时,TS 会进行检测。
类型断言 当 TS 推断出来的类型并不满足我们的使用需要时,可以使用类型断言来手动指定一个类型。
let  a : unknown  = [1 , 2 , 3 , 4 ];(a as  []).map (() =>  { }) 
非空断言 数组 定义方法:
let  arr1 : number [] = [1 , 2 , 3 , 4 ]let  arr2 : string [] = ['1' , '2' , '3' , '4' ]let  arr3 : Array <number > = [1 , 2 , 3 , 4 ]let  arr4 : Array <string > = ['1' , '2' , '3' , '4' ]let  arr5 : (string  | number )[] = ['1' , '2' , 3 , 4 ]
元祖 表示一个已知元素数量和类型的数组,各元素的类型不必相同。
注意定义的元素类型和元素的数量和它的类型必须一致。
let  arr1 : [string , number ] = ['1' , 1 ]let  arr2 : [string , number , string ] = ['1' , 2 , '3' ]
定义对象、可选属性、索引签名 type  Person  = {    name : string      age : number ,     sex?: string       [index : string ]: any   } const  person : Person  = {    name : 'John' ,     age : 30 ,     address : 'New York'   } 
需要注意的是,代码的提示只会提示定义的属性,不会提示索引签名的属性。
如上面会提示的属性有 name、age、address。
空数组、空对象 const  arr : number [] = [] type  ObjType  = {  name : string ,   age : number  } const  obj = {} as  ObjType  
定义函数、void类型 函数的实参个数和形参个数必须一致。
function  foo1  (a : string , b?:number ): number  {    return  123  } foo1 ('1' , 2 )const  foo2 = (a : string , b?: number ): number  =>    return  123  } foo2 ('1' , 2 )const  foo3 : (a: string , b?: number  ) =>  number  = (a, b ) =>  {    return  123  } foo3 ('1' , 2 )type  FooType  = (a: string , b?: number  ) =>  number const  foo4 : FooType  = (a, b ) =>  {    return  123  } foo4 ('1' , 2 )
void 类型是函数没有返回值的类型。
function  foo1  () { }function  foo2  (): void  {    return  } function  foo3  (): void  {    return  undefined  } 
如果返回的是 undefined 需要手动指定返回类型为 undefined。
函数重载 现在需要实现一个函数,它接受一个、两个、四个参数,不能只传三个参数,因为第三个、第四个参数是搭配一起的。
function  foo (n1: string  ): any function  foo (n1: string , n2: number  ): any function  foo (n1: string , n2: number , n3: string  ,n4: string  ): any function  foo (n1: string , n2?: number , n3?: string , n4?: string  ): any {}foo ('1' )foo ('1' , 2 )foo ('1' , 2 , '3' , '4' )
可调用注解 type  Foo  = {    (n1 : string ): any      (n1 : string , n2 : number ): any      (n1 : string , n2 : number , n3 : string , n4 : string ): any      username?: string   } function  foo (n1: string , n2?: number , n3?: string , n4?: string  ): any {}let  fn : Foo  = foofn ('1' )fn ('1' , 2 )fn ('1' , 2 , '3' , '4' )fn.username  = 'haha'  console .log (fn.username ) 
枚举 可以通过枚举的属性名获取枚举的值,也可以通过枚举的值获取枚举的属性名。
enum  UserType  {    SUPER_ADMIN ,     ADMIN ,     USER  } console .log (UserType .SUPER_ADMIN ) console .log (UserType .ADMIN ) console .log (UserType .USER ) console .log (UserType [0 ]) console .log (UserType [1 ]) console .log (UserType [2 ]) 
可以手动定义枚举的值。后面的枚举值会自动递增。
enum  UserType  {    SUPER_ADMIN ,     ADMIN  = 3 ,     USER  } console .log (UserType .SUPER_ADMIN ) console .log (UserType .ADMIN ) console .log (UserType .USER ) console .log (UserType [0 ]) console .log (UserType [3 ]) console .log (UserType [4 ]) 
也可以定义为字符串,但定义为字符串后,所有的枚举值都必须手动赋值。
enum  UserType  {    SUPER_ADMIN  = 'super_admin' ,     ADMIN  = 'admin' ,     USER  = 'user'  } console .log (UserType .SUPER_ADMIN ) console .log (UserType .ADMIN ) console .log (UserType .USER ) 
enum  UserType  {    SUPER_ADMIN  = 'super_admin' ,     ADMIN  = 2 ,     USER  = 'user'  } console .log (UserType .SUPER_ADMIN ) console .log (UserType .ADMIN ) console .log (UserType .USER ) 
const 枚举 未使用 const 定义的枚举,编译结果对比
enum  UserType  {    SUPER_ADMIN  = 'super_admin' ,     ADMIN  = 2 ,     USER  = 'user'  } console .log (UserType .SUPER_ADMIN ) console .log (UserType .ADMIN ) console .log (UserType .USER ) 
编译结果
var  UserType ;(function  (UserType ) {     UserType ["SUPER_ADMIN" ] = "super_admin" ;     UserType [UserType ["ADMIN" ] = 2 ] = "ADMIN" ;     UserType ["USER" ] = "user" ; })(UserType  || (UserType  = {})); console .log (UserType .SUPER_ADMIN ); console .log (UserType .ADMIN ); console .log (UserType .USER ); 
使用 const 定义的枚举,会在编译时被移除,不会生成对应的代码。
const  enum  UserType  {    SUPER_ADMIN  = 'super_admin' ,     ADMIN  = 2 ,     USER  = 'user'  } console .log (UserType .SUPER_ADMIN ) console .log (UserType .ADMIN ) console .log (UserType .USER ) 
编译后
console .log ("super_admin"  ); console .log (2  ); console .log ("user"  ); 
接口 与 类型别名 的区别 接口是一系列抽象方法的声明,是一些方法特征的集合。
简单来说,接口的作用就是为这些类型命名和为我们的代码或第三方代码定义契约。
区别:
接口主要用于对象类型,类型别名均可以。 
相同接口定义可以进行合并,类型别名不行。 
接口支持继承,类型别名不行。 
类型别名支持映射类型,接口不支持。 
 
type  A = string type  B = number []interface  C { }interface  D {    a : string  } interface  D {    b : string   } const  e : D = {    a : 'a' ,     b : 'b'  } interface  F extends  D {    c : string  } 
字面量类型 可以把字面量作为具体的类型使用,需要注意的是,该类型的取值就必须是该字面量的值。
type  Type  = 'admin'  | 'test' const  userType : Type  = 'admin' 
keyof 关键字 interface  IObj  {  name : string    age : number  } const  user : keyof IObj  = 'age' const  obj = {    name : 'lisi' ,     age : 18  } const  user2 : keyof typeof  obj = 'age' 
类型保护 类型保护允许我们使用更小范围下的对象类型。
typeof 
instanceof 
in 
字面量类型 
 
function  fn (n: number  | string  ) {    if  (typeof  n === 'string' ) {       console .log (n.length )   } } class  userName  {    name!: string   } class  userAge  {    age!: number  } function  fn1 (n: userName | userAge ) {    if  (n instanceof  userName) {         console .log (n.name )     }     } function  fn2 (n: {name: string } | {age: number } ) {    if  ('name'  in  n) {         console .log (n.name )     } } function  fn3 (n: 'a'  | 123  ) {    if  (n === 'a' ) {         console .log (n.length )     } } 
自定义类型保护 function  isStr (n: any  ): n is string  {    return  typeof  n === 'string'  } function  fn (n: number  | string  ) {    if  (isStr (n)) {       console .log (n.length )   } } fn ('123' )
泛型 指在定义函数、接口或类时,未指定参数类型,在运行时才确定。
type  A<T> = Tconst  a : A<string > = 'string' const  b : A<number > = 1 interface  IA<T> {    (n : T): T     name?: T } const  c : IA <string > = (n : string ): string  =>return  n}c.name  = 'string'  function  fn<T> (n : T): T {    return  n } fn (1 )class  AClass <T> {    name : T     constructor  (name : T) {         this .name  = name     }     getName (): T {         return  this .name      }     setName (n : T): string  {         this .name  = n          return  'success'      } } const  d = new  AClass <string >('string' )console .log (d.getName ())console .log (d.setName ('haha' ))
泛型约束 class  AClass <T> {    name : T     constructor  (name : T) {         this .name  = name     } } const  d = new  AClass <string >('123' ) const  e = new  AClass <number >(123 )class  BClass  extends  AClass <string > { } const  f = new  BClass ('string' )type  B = string function  fn1<T extends  B> (n : T): T {     return  n } fn1 ('string' )
类型兼容性 类型兼容性用于确定一个类型是否能赋值给其他类型。
let  a : string  = '123' let  b : string  | number  = 123 b = a  interface  A {    a : number  } interface  B {    a : number      b : string  } let  c : A = { a : 1  }let  d : B = { a : 1 , b : '1'  }c = d  function  fn ({ a: number  } ) {}fn ({ a : 1  })const  value = { a : 1 , b : 2  }fn (value) 
对于基础类型来说,少的可以赋值给多的。
映射类型 只能通过 类型别名 来定义映射类型。不能使用 接口 来定义映射类型。
type  A = {    username : string      age : number  } type  B = {    [p in  keyof A]: A[p] } const  a : B = { username : 'ss' , age : 12  }
keyof A 是获取类型 A 的所有属性名的联合类型,即 'username' | 'age'。p in keyof A 是遍历类型 A 的所有属性名,即 'username' | 'age'。A[p] 是获取 当前遍历属性 p 在 类型 A 中的类型,即 string | number。
内置工具类型 type  A = {    username : string      age : number      gender?: string ,     readonly  address?: string  } type  a = Readonly <A> type  b = Partial <A> type  c = Pick <A, 'username'  | 'age' > type  d = Record <'age' , string > type  e = Record <keyof A, string >type  f = Required <A> type  g = Exclude <string  | number  | boolean , boolean > type  h = Extract <string  | number  | boolean , boolean > type  i = Omit <A, 'username'  | 'age' > type  j = NonNullable <string  | number  | undefined  | null > 
infer 关键字 type  A<T> = T extends  Array <infer U> ? U : Ttype  B = A<Array <number >>type  C = A<string >
类如何使用类型 类中定义类型 class  A  {    username!: string  } class  B  {    username : string  = 'zhangsan'  } class  C  {    username : string      constructor  (username : string ) {         this .username  = username     } } const  a = new  A ()a.username  = 'zhangsan'  const  b = new  B ()b.username  = 'zhangsan'  const  c = new  C ('zhangsan' )console .log (a, b, c); c.username  = 'lisi'  console .log (a, b, c); 
类使用接口 interface  IA {    username : string      getUserInfo (age : number ): string  } class  A  implements  IA  {    username : string  = '张三'      getUserInfo (age : number ): string  {         return  `我叫${this .username} ,今年${age} 岁了`      } } const  a = new  A ()console .log (a.getUserInfo (18 ))
类使用泛型 class  A <T> {    username : T     constructor (username: T ) {         this .username  = username     } } const  a = new  A<string >('123' )class  B  extends  A <number >{ }const  b = new  B (123 )interface  IA<T> {    username : T     getUserInfo (age : number ): string  } class  A  implements  IA <string > {    username : string  = '张三'      getUserInfo (age : number ): string  {         return  `我叫${this .username} ,今年${age} 岁了`      } } const  a = new  A ()console .log (a.getUserInfo (18 ))