1、常用类型

1.1 穿插类型

穿插类型便是经过 & 符号,将多个类型兼并为一个类型。

interface T1 {
  name: string;
}
interface T2 {
  age: number;
}
type T3 = T2 & T1
const a: T3 = {
  name: 'xm',
  age: 20,
}

1.2 联合类型

联合类型便是经过 | 符号,表明一个值能够是几种类型之一。

const a: string | number = 1

1.3 字面量类型

字面量类型便是运用一个字符串或数字或布尔类型作为变量的类型。

// 字符串
type BtnType ='default'| 'primary'| 'ghost'| 'dashed'| 'link'| 'text';
const btn:BtnType= 'primary'
// 数字
const a: 1 = 1
// 布尔
const a: true = true

1.4 字符串模板类型

字符串模板类型便是经过 ES6 的模板字符串语法,对类型进行束缚。

type https = `https://${string}`
const a:https = `https://www.baidu.com`

2、运算符

2.1 非空断语运算符

非空断语运算符 ! 用于强调元素对错 null 非 undefined,告诉 Typescript 该特点会被清晰的赋值。

// 你能够运用类型断语将其指定为一个更详细的类型:
const myCanvas = document.getElementById("main_canvas") as HTMLCanvasElement;
// 也能够运用尖括号语法(留意尽量不要在 .tsx 文件内运用,会产生冲突),是等价的:
const myCanvas = <HTMLCanvasElement>document.getElementById("main_canvas");
// 当你清晰的知道这个值不可能是 null 或者 undefined 时才运用 ! 
function liveDangerously(x?: number | null) {
  console.log(x!.toFixed());
}

2.2 可选运算符

可选链运算符 ?. 用于判断左边表达式的值是否是 null 或 undefined,如果是将停止表达式运转。

const name = object?.name

2.3 空值兼并运算符

空值兼并运算符 ?? 用于判断左边表达式的值是否是 null 或 undefined,如果是返回右侧的值。

const a = b ?? 0

3、操作符

3.1 keyof

keyof 用于获取某种类型的一切键,其返回值是联合类型。

const person: keyof {
  name: string,
  age: number
} = 'name'   //const person: 'name' | 'age' = 'name'

3.2 typeof

typeof 用于获取目标或者函数的结构类型。

const a2 = {
  name: 'xm',
}
type T1 = typeof a2 // { name: string }
function fn1(x: number): number {
  return x * 10
}
type T2 = typeof fn1 // (x: number) => number

3.3 in

in 用于遍历联合类型。

const obj = {
  name: 'xm',
  age: 20,
  sex:'男'
}
type T5 = {
  [P in keyof typeof obj]: string
}
/*
{ name: string, age: string, sex:string }
*/

3.4 T[K]

T[K] 用于拜访索引,得到索引对应的值的联合类型。

interface I3 {
  name: string,
  age: number
}
type T6 = I3[keyof I3] // string | number

4、类型别号

类型别号用来给一个类型起个新姓名。类型别号常用于联合类型。这里需求留意的是咱们仅仅是给类型取了一个新的姓名,并不是创建了一个新的类型

type Message = string | string[]
let greet = (message: Message) => {
  // ...
}

5、类型断语

类型断语便是告诉浏览器我非常确定的类型。

// 尖括号 语法
let someValue: any = "this is a string";
let strLength: number = (<string>someValue).length;
// as 语法
let someValue: any = "this is a string";
let strLength: number = (someValue as string).length;

6、类型缩小

咱们能够经过某些操作将变量的类型由一个较为宽泛的调集缩小到相对较小、较清晰的调集

 let func = (anything: string | number) => {
    if (typeof anything === 'string') {
      return anything; // 类型是 string 
    } else {
      return anything; // 类型是 number
    }
  };

7、泛型

泛型便是经过给类型传参,得到一个愈加通用的类型,就像给函数传参一样。
如下咱们得到一个通用的泛型类型 T1,经过传参,能够得到 T2 类型 string[]、T3 类型 number[]; T 是变量,咱们能够用恣意其他变量名代替他。

type T1<T> = T[]
type T2 = T1<string> // string[]
type T3 = T1<number> // number[]

7.1 常见泛型界说

  • T:表明第一个参数
  • K: 表明目标的键类型
  • V:表明目标的值类型
  • E:表明元素类型

7.2 泛型接口

泛型接口和上述示例相似,为接口类型传参:

interface I1<T, U> {
  name: T;
  age: U;
}
type I2 = I1<string, number>

7.3 泛型束缚

Typescript 经过 extends 完成类型束缚。让传入值满意特定条件;

interface IWithLength {
  length:number
}
function echoWithLength<T extends IWithLength>(arg:T):T{
  console.log(arg.length)
  return arg
}
echoWithLength('str')

经过 extends 束缚了 K 必须是 T 的 key。

function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
    return obj[key];
}
let tsInfo = {
    name: "Typescript",
    supersetOf: "Javascript",
    difficulty: Difficulty.Intermediate
}
let difficulty: Difficulty =
    getProperty(tsInfo, 'difficulty'); // OK
let supersetOf: string =
    getProperty(tsInfo, 'superset_of'); // Error

7.4 泛型参数默认值

泛型参数默认值,和函数参数默认值一样,在没有传参时,给定默认值。

interface I4<T = string> {
  name: T;
}
const S1: I4 = { name: '123' } // 默认 name: string类型
const S2: I4<number> = { name: 123 }

7.5 泛型工具类型

7.5.1 typeof

typeof 的主要用途是在类型上下文中获取变量或者特点的类型;

interface Person {
  name: string;
  age: number;
}
const sem: Person = { name: "semlinker", age: 30 };
type Sem = typeof sem; // type Sem = Person
// 运用Sem类型
const lolo: Sem = { name: "lolo", age: 5 } 

7.5.2 keyof

keyof 能够用于获取某种类型的一切键,其返回类型是联合类型。

interface Person {
  name: string;
  age: number;
}
type K1 = keyof Person; // "name" | "age"
type K2 = keyof Person[]; // "length" | "toString" | "pop" | "push" | "concat" | "join" 
type K3 = keyof { [x: string]: Person };  // string | number

7.5.3 映射类型

映射类型,它是一种泛型类型,可用于把原有的目标类型映射成新的目标类型。

interface TestInterface{
    name:string,
    age:number
}
// 咱们能够经过+/-来指定添加还是删除
// 把上面界说的接口里面的特点悉数变成可选
type OptionalTestInterface<T> = {
  [p in keyof T]+?:T[p]
}
// 再加上只读
type OptionalTestInterface<T> = {
  +readonly [p in keyof T]+?:T[p]
}
type newTestInterface = OptionalTestInterface<TestInterface>

7.5.4 Partial

Partial 将类型的特点变成可选

type Partial<T> = {
  [P in keyof T]?: T[P]
}
type T1 = Partial<{
  name: string,
}>
const a: T1 = {} // 没有name特点也不会报错

7.5.5 Required

Required 将泛型的一切特点变为必选。

// 语法-?,是把?可选特点减去的意思
type Required<T> = {
  [P in keyof T]-?: T[P]
}
type T2 = Required<{
  name?: string,
}>
// ts报错,类型 "{}" 中短少特点 "name",但类型 "Required<{ name?: string | undefined; }>" 中需求该特点。ts(2741)
const b: T2 = {}

7.5.6 Readonly

Readonly 将泛型的一切特点变为只读。

type T3 = Readonly<{
  name: string,
}>
const c: T3 = {
  name: 'tj',
}
c.name = 'tj1' // ts 报错,无法分配到 "name" ,因为它是只读特点。ts(2540)

7.5.7 Pick

Pick 从类型中选择一下特点,生成一个新类型。

// 比如一
type Pick<T, K extends keyof T> = {
  [P in K]: T[P]
}
type T4 = Pick<
  {
    name: string,
    age: number,
  },
  'name'
>
/*
这是一个新类型,T4={name: string}
*/
const d: T4 = {
  name: 'tj',
}
// 比如二
interface Todo {
  title: string;
  description: string;
  completed: boolean;
}
type TodoPreview = Pick<Todo, "title" | "completed">;
const todo: TodoPreview = {
  title: "Clean room",
  completed: false,
};

7.5.8 Record

Record 将 key 和 value 转化为 T 类型。

// 比如一
type Record<K extends keyof any, T> = {
  [key in K]: T
}
const e: Record<string, string> = {
  name: 'tj',
}
const f: Record<string, number> = {
  age: 11,
}
// 比如二
interface PageInfo {
  title: string;
}
type Page = "home" | "about" | "contact";
const x: Record<Page, PageInfo> = {
  about: { title: "about" },
  contact: { title: "contact" },
  home: { title: "home" },
};

7.5.9 Exclude

Exclude 将某个类型中属于另一个的类型移除去。

type Exclude<T, U> = T extends U ? never : T;
type T0 = Exclude<"a" | "b" | "c", "a">; // "b" | "c"
type T1 = Exclude<"a" | "b" | "c", "a" | "b">; // "c"
type T2 = Exclude<string | number | (() => void), Function>; // string | number

7.5.10 Extract

Extract 从 T 中提取出 U。

type Extract<T, U> = T extends U ? T : never;
type T0 = Extract<"a" | "b" | "c", "a" | "f">; // "a"
type T1 = Extract<string | number | (() => void), Function>; // () =>void

7.5.11 Omit

Omit 运用 T 类型中除了 K 类型的一切特点,来构造一个新的类型。

type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
interface Todo {
  title: string;
  completed: boolean;
  description: string;
}
type TodoPreview = Omit<Todo, "description">;
/*
{
  title: string;
  completed: boolean;
}
*/

7.5.12 Parameters

Parameters<T>的效果是用于取得函数的参数类型组成的元组类型。

funtion test(id:number, name:string){ ... }
type TestArgsType = Parameters<typeof test>;
/*
[id:number,name:string]
*/

7.5.13 ReturnType

用来得到一个函数的返回值类型。

typeFunc=(value:number)=>string;
constfoo:ReturnType<Func>="xxx";

8、类型别号与接口区别

8.1 界说

接口:接口的效果便是为这些类型命名和为你的代码或第三方代码界说数据模型。
类型别号:type(类型别号)会给一个类型起个新姓名。 type 有时和 interface 很像,但是能够效果于原始值(根本类型),联合类型,元组以及其它任何你需求手写的类型。

8.2 Objects / Functions

两者都能够用来描述目标或函数的类型,但是语法不同。

// interface
interface Point {
  x: number;
  y: number;
}
interface SetPoint {
  (x: number, y: number): void;
}
// type
type Point = {
  x: number;
  y: number;
};
type SetPoint = (x: number, y: number) => void;

8.3 type界说其他类型

与接口不同,类型别号还能够用于其他类型,如根本类型(原始值)、联合类型、元组。

// primitive
type Name = string;
// object
type PartialPointX = { x: number; };
type PartialPointY = { y: number; };
// union
type PartialPoint = PartialPointX | PartialPointY;
// tuple
type Data = [number, string];
// dom
let div = document.createElement('div');
type B = typeof div;

8.4 接口能够界说屡次,类型别号不能够

与类型别号不同,接口能够界说屡次,会被主动兼并为单个接口。

interface Point { x: number; }
interface Point { y: number; }
const point: Point = { x: 1, y: 2 };

8.5 扩展

两者都能够扩展,接口经过 extends 来完成。类型别号的扩展便是穿插类型,经过 & 来完成。

// 接口扩展接口
interface PointX {
    x: number
}
interface Point extends PointX {
    y: number
}
// 类型别号扩展类型别号
type PointX = {
    x: number
}
type Point = PointX & {
    y: number
}
// 接口扩展类型别号
type PointX = {
    x: number
}
interface Point extends PointX {
    y: number
}
// 类型别号扩展接口
interface PointX {
    x: number
}
type Point = PointX & {
    y: number
}

9、参考资料

  • 2021 typescript史上最强学习入门文章(2w字)

  • Ts官网