interface Foo {bar: number;bas: string;}const foo = {} as Foo;foo.bar = 123;foo.bas = 'hello';
function doSome(x: number | string) {if (typeof x === 'string') {// 在这个块中,TypeScript 知道 `x` 的类型必须是 `string`console.log(x.subtr(1)); // Error: 'subtr' 方法并没有存在于 `string` 上console.log(x.substr(1)); // ok}x.substr(1); // Error: 无法保证 `x` 是 `string` 类型}
class Foo {foo = 123;common = '123';}class Bar {bar = 123;common = '123';}function doStuff(arg: Foo | Bar) {if (arg instanceof Foo) {console.log(arg.foo); // okconsole.log(arg.bar); // Error} else {// 这个块中,一定是 'Bar'console.log(arg.foo); // Errorconsole.log(arg.bar); // ok}}doStuff(new Foo());
interface A {x: number;}interface B {y: string;}function doStuff(q: A | B) {if ('x' in q) {// q: A} else {// q: B}}
type Man = {handsome: 'handsome';type: 'man';};type Woman = {beautiful: 'beautiful';type: 'woman';};function Human(arg: Man | Woman) {if (arg.type === 'man') {console.log(arg.handsome);console.log(arg.beautiful); // error} else {// 这一块中一定是 Womanconsole.log(arg.beautiful);}}
function handler(event: Event) {const element = event as HTMLElement; // Error: 'Event' 和 'HTMLElement' 中的任何一个都不能赋值给另外一个}function handler(event: Event) {const element = event as any as HTMLElement; // ok}
将所有属性都设置未可选的类型。将返回给定类型的所有子集的类型
type Partial<T> = {[P in keyof T]?: T[P];};interface Todo {title: string;description: string;}function updateTodo(todo: Todo, fieldsToUpdate: Partial<Todo>) {return { ...todo, ...fieldsToUpdate };}const todo1 = {title: 'organize desk',description: 'clear clutter',};const todo2 = updateTodo(todo1, {description: 'throw out trash', //👍});
所有属性都设置为只读,因此属性值不能被赋值。
type Readonly<T> = {readonly [P in keyof T]: T[P];};type Foo = {readonly bar: number;readonly bas: number;};// 初始化const foo: Foo = { bar: 123, bas: 456 };// 不能被改变foo.bar = 456; // Error: foo.bar 为仅读属性
用于将一个类型属性映射到另一个类型。
type Record<K extends string, T> = {[P in K]: T;};interface CatInfo {age: number;breed: string;}type CatName = 'miffy' | 'boris' | 'mordred';const cats: Record<CatName, CatInfo> = {miffy: { age: 10, breed: 'Persian' },boris: { age: 5, breed: 'Maine Coon' },mordred: { age: 16, breed: 'British Shorthair' },};cats.boris;// ^ = const cats: Record<CatName, CatInfo>
从一个构造对象中挑选类型
interface Todo {title: string;description: string;completed: boolean;}type TodoPreview = Pick<Todo, 'title' | 'completed'>;const todo: TodoPreview = {title: 'Clean room',completed: false,};todo;// ^ = const todo: TodoPreview
从一个构造对象中移除某些属性
interface Todo {title: string;description: string;completed: boolean;}type TodoPreview = Omit<Todo, 'description'>;const todo: TodoPreview = {title: 'Clean room',completed: false,};todo;// ^ = const todo: TodoPreview
Exclude<Type, ExcludedUnion> 去除Type
中包含ExcludedUnion
的属性
type T0 = Exclude<'a' | 'b' | 'c', 'a'>;// ^ = type T0 = "b" | "c"type T1 = Exclude<'a' | 'b' | 'c', 'a' | 'b'>;// ^ = type T1 = "c"type T2 = Exclude<string | number | (() => void), Function>;// ^ = type T2 = string | number
Extract<Type, Union> 取Type
和Union
都存在的属性
type T0 = Extract<'a' | 'b' | 'c', 'a' | 'f'>;// ^ = type T0 = "a"type T1 = Extract<string | number | (() => void), Function>;// ^ = type T1 = () => void
构造一个由函数类型的返回类型组成的类型。
type T0 = ReturnType<() => string>;// ^ = type T0 = stringtype T1 = ReturnType<(s: string) => void>;// ^ = type T1 = voidtype T2 = ReturnType<<T>() => T>;// ^ = type T2 = unknown
取出函数参数作为类型。
type T1 = Parameters<(a: string) => void>;// [a:string]type T2 = Parameters<() => {}>;// []declare function f1(arg: { a: number; b: string }): void;type T3 = Parameters<typeof f1>;// [arg:{a:number,b:string}]
NonNullable<Type>
去除 null、undefined
type T0 = NonNullable<string | null | undefined | number>;// type T0=string| number
Any: 是所有类型的 top type 即所有类型都可以赋值给它。
let uncertain: any = 'Hello world'!;uncertain = 5;uncertain = { hello: () => 'Hello world!' };
同时使用any
也意味这放弃了 Typescript 类型检查
const uncertain: any = 'Hello world!';uncertain.hello(); //TypeError: uncertain.hello is not a function
Unknown: 该类型也被认为是top type
,但它更具有类型安全。所有类型都可以赋值给它就像any
一样
let uncertain: unknown = 'Hello'!;uncertain = 12;uncertain = { hello: () => 'Hello!' };
const dog: unknown = getDog();dog.hello(); // Unable to compile TypeScript: Property ‘hello’ does not exist on type ‘unknown’.
const number: unknown = 15;(number as string).toLowerCase(); // TypeError: number.toLowerCase is not a function
总结: unknown 类型要安全得多,因为它迫使我们执行额外的类型检查来对变量执行操作。
return
我们会收到 undefined,为了忽略它我们使用 void
表示Never
表示返回值function sayHello(): void {console.log('Hello world!');}function throwUserNotFoundError(userId: number): never {throw new Error(`User with id ${userId} is not found`);}
interface 是接口,type 是类型,本身就是两个概念,只是碰巧表现上比较相似。
希望定义一个变量类型,就用 type,如果希望是能够继承并约束的,就用 interface。
如果你不知道该用哪个,说明你只是想定义一个类型而非接口,所以应该用 type。