包含最重要基础、泛型、方法、class 等 TypeScript 强类型编程语言语法的快速参考备忘单。初学者的完整快速参考
入门 Interface 介绍 TypeScript 是具有类型语法的 JavaScript。Interface 是为了匹配它们的运行时行为而构建的。
内置类型基元 1 2 3 4 5 any , void ,boolean , string , number ,undefined , null ,unknown , never ,bigint , symbol
常见的内置 JS 对象 1 2 3 Date , Error ,Array , Map , Set ,Regexp , Promise
内置 类型字面量 Object:
Function:
Arrays:
1 string [] or Array <string >
Tuple:
避免 1 Object , String , Number , Boolean
通用语法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 interface JSON Response extends Response , HTTPAble { version : number ; payloadSize : number ; outOfStock?: boolean ; update : (retryTimes: number ) => void ; update (retryTimes : number ): void ; (): JSON Response new (s : string ): JSON Response; [key : string ]: number ; readonly body : string ; }
泛型 声明一个可以在你的 Interface 中改变的类型
1 2 3 interface APICall <Response > { data : Response }
用法 1 2 3 const api : APICall <ArtworkCall > = ...api.data
您可以通过 extends
关键字限制泛型参数接受的类型。
1 2 3 4 5 6 7 interface APICall <Response extends { status : number }> { data : Response } const api : APICall <ArtworkCall > = ...api.data .status
重载 1 2 3 4 interface Expect { (matcher : boolean ): string (matcher : string ): boolean ; }
一个可调用 Interface 可以对不同的参数集有多个定义。
类一致性 1 2 3 4 interface Syncable { sync (): void } class Account implements Syncable { ... }
您可以通过实现确保类 class 符合 Interface。
Get & Set 对象可以有自定义的 getter
或 setter
。
1 2 3 4 interface Ruler { get size (): number set size (value: number | string ); }
用法
1 2 3 const r : Ruler = ...r.size = 12 r.size = "36"
通过合并扩展 1 2 3 4 5 6 7 interface APICall { data : Response } interface APICall { error?: Error }
Interface 被合并,多个声明将向类型定义添加新字段。
Type Type vs Interface
Interface 只能描述对象形状
Interface 可以通过多次声明来扩展
在性能关键 Type 中,Interface 比较检查可以更快。
把类型想象成变量 就像您如何在不同范围内创建具有相同名称的变量一样,type 具有相似的语义。
使用实用程序类型构建 TypeScript 包含许多全局类型,它们将帮助您在类型系统中完成常见任务。检查他们的网站。
原始类型 1 2 type SanitizedInput = string ;type MissingNo = 404 ;
主要用于文档
对象字面类型 1 2 3 4 type Location = { x : number ; y : number ; };
联合类型 1 type Size = "small" | "medium" | "large"
描述许多选项中的一个类型,例如已知字符串的列表。
交叉口类型 1 2 3 type Location = { x : number } & { y : number }
一种合并/扩展类型的方法
从值类型 1 2 const data = { ... }type Data = typeof data
通过 typeof 运算符重用来自现有 JavaScript 运行时值的类型。
从函数返回类型 1 2 3 const createFixtures = ( ) => { ... }type Fixtures = ReturnType <typeof createFixtures>function test (fixture: Fixtures ) {}
将函数的返回值重新用作类型。
从模块类型 1 const data : import ("./data" ).data
这些功能非常适合构建库、描述现有的 JavaScript 代码,您可能会发现在大多数 TypeScript 应用程序中很少使用它们。
对象字面量语法 1 2 3 4 5 6 7 8 9 10 11 12 type JSON Response = { version : number ; payloadSize : number ; outOfStock?: boolean ; update : (retryTimes: number ) => void ; update (retryTimes : number ): void ; (): JSON Response [key : string ]: number ; new (s : string ): JSON Response; readonly body : string ; }
用于节省空间的 Terser,请参阅 Interface 备忘清单了解更多信息,除了“static”匹配之外的所有内容。
映射类型 1 2 3 4 5 6 7 8 9 10 11 type Artist = { name : string , bio : string } type Subscriber <Type > = { [Property in keyof Type ]: (newValue: Type[Property] ) => void } type ArtistSub = Subscriber <Artist >
类似于类型系统的映射语句,允许输入类型更改新类型的结构。
模板联合类型 1 2 3 4 5 6 7 type SupportedLangs = "en" | "pt" | "zh" ;type FooterLocaleIDs = "header" | "footer" ;type AllLocaleIDs = `${SupportedLangs} _${FooterLocaleIDs} _id` ;
条件类型 1 2 3 4 type HasFourLegs <Animal > = Animal extends { legs : 4 } ? Animal : never type Animals = Bird | Dog | Ant | Wolf ;type FourLegs = HasFourLegs <Animals >
在类型系统中充当“if 语句”。 通过泛型创建,然后通常用于减少类型联合中的选项数量。
控制流动分析 If 声明 typeof(用于原语) 1 2 3 4 5 6 const input = getUserInput ()input if (typeof input === 'string' ) { input }
对象中的“property”(对于对象) 1 2 3 4 5 6 const input = getUserInput ()input if ('error' in input) { input }
instanceof(用于类) 1 2 3 4 5 6 const input = getUserInput () input if (input instanceof Array ) { input }
类型保护功能(适用于任何东西) 1 2 3 4 5 6 const input = getUserInput () input if (Array .isArray (input)) { input }
任务 1 2 3 4 5 6 const data1 = { name : "Zagreus" }
👇 使用 as const
缩小类型 👇
1 2 3 4 5 6 const data2 = { name : "Zagreus" } as const
跟踪相关变量
1 2 3 4 5 6 7 const response = getResponse ()const isSuccessResponse = res instanceof SuccessResponse if (isSuccessResponse) { res.data }
重新分配更新类型
1 2 3 4 let data : string | number = ...data data = "Hello" data
关键点 CFA 几乎总是采用联合,并根据代码中的逻辑减少联合内的类型数量。
大多数时候 CFA 在自然 JavaScript 布尔逻辑中工作,但是有一些方法可以定义您自己的函数,这些函数会影响 TypeScript 如何缩小类型。
表达式 1 2 3 4 5 6 const input = getUserInput ()input const inputLength = (typeof input === "string" && input.length ) || input
在进行布尔运算时,缩窄也发生在与代码相同的行上
可识别联合 1 2 3 4 type Responses = | { status : 200 , data : any } | { status : 301 , to : string } | { status : 400 , error : Error }
用法 1 2 3 4 5 6 7 const response = getResponse ()response switch (response.status ) { case 200 : return response.data case 301 : return redirect (response.to ) case 400 : return response.error }
断言函数 描述影响当前范围的 CFA 更改的函数,因为它抛出而不是返回 false。
1 2 3 4 5 function assertResponse (obj: any ): asserts obj is SuccessResponse { if (!(obj instanceof SuccessResponse )) { throw new Error ('Not a success!' ) } }
用法 1 2 3 4 5 6 7 const res = getResponse ():res assertResponse (res)res
in 操作符 1 2 3 4 5 6 7 8 9 10 11 12 13 14 interface A { x : number ; } interface B { y : string ; } function doStuff (q: A | B ) { if ('x' in q) { } else { } }
操作符可以安全的检查一个对象上是否存在一个属性,它通常也被作为类型保护使用
Class 创建类实例 1 2 class ABC { ... }const abc = new ABC ()
新 ABC 的参数来自构造函数。
private x 与 #private 前缀 private 是一个仅类型的添加,在运行时没有任何影响。 在以下情况下,类之外的代码可以进入项目:
1 2 3 class Bag { private item : any }
Vs #private 是运行时私有的,并且在 JavaScript 引擎内部强制执行,它只能在类内部访问:
1 class Bag { #item : any }
Class 上的 “this” 函数内部‘this’的值取决于函数的调用方式。 不能保证始终是您可能在其他语言中使用的类实例。
您可以使用“此参数”、使用绑定功能或箭头功能来解决问题。
类型和值 一个类既可以用作类型也可以用作值。
所以,小心不要这样做:
1 class C implements Bag {}
通用语法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 class User extends Account implements Updatable , Serializable { id : string ; displayName?: boolean ; name!: string ; #attributes : Map <any , any >; roles = ["user" ]; readonly createdAt = new Date () constructor (id: string , email: string ) { super (id); this .email = email; }; setName (name: string ) { this .name = name } verifyName = (name: string ) => { } sync (): Promise <{ ... }> sync (cb : ((result: string ) => void )): void sync (cb?: ((result: string ) => void )): void | Promise <{ ... }> {} get accountID () { } set accountID (value: string ) { } private makeRequest ( ) { ... } protected handleRequest ( ) { ... } static #userCount = 0 ; static registerUser (user: User ) { ... } static { this .#userCount = -1 } }
泛型 声明一个可以在你的类方法中改变的类型。
1 2 3 4 5 6 7 class Box <Type > { contents : Type constructor (value: Type ) { this .contents = value; } } const stringBox = new Box ("a package" )
这些功能是 TypeScript 特定的语言扩展,可能永远无法使用当前语法进入 JavaScript。
参数属性 1 2 3 4 5 6 7 8 9 10 class Location { constructor ( public x: number , public y: number ) {}} const loc = new Location (20 , 40 );loc.x loc.y
TypeScript 特定于类的扩展,可自动将实例字段设置为输入参数。
抽象类 1 2 3 4 5 6 7 8 9 abstract class Animal { abstract getName (): string ; printName ( ) { console .log ("Hello, " + this .getName ()); } } class Dog extends Animal { getName (): { ... } }
一个类可以被声明为不可实现,但可以在类型系统中被子类化。 class 成员也可以。
装饰器和属性 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import { Syncable , triggersSync, preferCache, required } from "mylib" @Syncable class User { @triggersSync () save ( ) { ... } @preferCache (false ) get displayName () { ... } update (@required info: Partial<User> ) { } }
您可以在类、类方法、访问器、属性和方法参数上使用装饰器。
索引签名 1 2 3 4 5 6 7 8 9 10 class MyClass { [s : string ]: boolean | ((s: string ) => boolean ); check (s: string ) { return this [s] as boolean ; } }
类可以声明索引签名,与其他对象类型的索引签名相同。
在 forwardRef 上面声明泛型 1 2 3 4 5 6 7 8 9 10 export const Wrapper = forwardRef ( <T extends object > ( props: RootNodeProps<T>, ref: React.LegacyRef<HTMLDivElement> ) => { return ( <div ref ={ref} > </div > ); }
实用程序类型 Awaited<Type> 1 2 3 4 5 6 7 8 type A = Awaited <Promise <string >>;type B = Awaited <Promise <Promise <number >>>;type C = Awaited <boolean |Promise <number >>;
这种类型旨在模拟异步函数中的 await 或 Promises 上的 .then() 方法等操作 - 特别是它们递归解包 Promises 的方式。
Required<Type> 1 2 3 4 5 6 7 8 9 interface Props { a?: number ; b?: string ; } const obj : Props = { a : 5 }; const obj2 : Required <Props > = { a : 5 };
使 Type 中的所有属性成为必需
Readonly<Type> 1 2 3 4 5 6 7 8 9 10 11 interface Todo { title : string ; } const todo : Readonly <Todo > = { title : "Delete inactive users" , }; todo.title = "Hello" ; function freeze<Type >(obj : Type ) : Readonly <Type >;
将 Type 中的所有属性设为只读
Partial<Type> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 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
中的所有属性设为可选
Record<Keys, Type> 1 2 3 4 5 6 7 8 9 10 11 12 13 interface CatInfo { age : number ; breed : string ; } type CatName = "miffy" | "boris" ;const cats : Record <CatName , CatInfo > = { miffy : {age :10 , breed : "Persian" }, boris : {age :5 , breed : "Maine Coon" }, }; cats.boris ;
构造一个具有一组 Keys 类型的属性 Type 的类型
Pick<Type, Keys> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 interface Todo { name : string ; description : string ; completed : boolean ; } type TodoPreview = Pick < Todo , "name" | "load" >; const todo : TodoPreview = { name : "Clean room" , load : false , }; todo;
从 Type 中选择 一组其键在并集 Keys 中的属性
Exclude<UnionType, ExcludedMembers> 1 2 3 4 5 6 7 8 9 type T0 = Exclude <"a" | "b" | "c" , "a" >;type T1 = Exclude <"a" |"b" |"c" , "a" | "b" >;type T2 = Exclude <string | number | (() => void ), Function >;
从 UnionType
中排除 那些可分配给 ExcludedMembers
的类型
1 2 3 4 5 6 7 8 9 type T0 = Extract < "a" | "b" | "c" , "a" | "f" >; type T1 = Extract < string | number | (() => void ), Function >;
通过从 Type 中提取 所有可分配给 Union 的联合成员来构造一个类型。
NonNullable<Type> 1 2 3 4 5 6 7 8 9 type T0 = NonNullable < string | number | undefined >; type T1 = NonNullable < string [] | null | undefined >;
通过从 Type 中排除 null 和 undefined 来构造一个类型。
Omit<Type, Keys> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 interface Todo { name : string ; completed : boolean ; createdAt : number ; } type TodoPreview = Omit <Todo , "name" >;const todo : TodoPreview = { completed : false , createdAt : 1615544252770 , }; todo;
构造一个具有 Type 属性的类型,但类型 Keys 中的属性除外 。
Parameters<Type> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 declare function f1 ( arg: { a: number ; b: string } ): void ;type T0 = Parameters <() => string >;type T1 = Parameters <(s: string ) => void >;type T2 = Parameters <<T>(arg: T ) => T>;type T3 = Parameters <typeof f1>;type T4 = Parameters <any >;type T5 = Parameters <never >;
从函数类型 Type 的参数中 使用的类型构造元组类型。
ConstructorParameters<Type> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 type T0 = ConstructorParameters < ErrorConstructor >; type T1 = ConstructorParameters < FunctionConstructor >; type T2 = ConstructorParameters < RegExpConstructor >; type T3 = ConstructorParameters <any >;
从构造函数类型的类型构造元组或数组类型。它产生一个包含所有参数类型的元组类型(如果 Type 不是函数,则类型 never )。
内在字符串操作类型 Uppercase<StringType> 1 2 3 4 5 6 7 type Greeting = "Hello, world" type ShoutyGreeting = Uppercase <Greeting >type ASCIICacheKey <Str extends string > = `ID-${Uppercase<Str>} ` type MainID = ASCIICacheKey <"my_app" >
将字符串中的每个字符转换为大写 版本。
Lowercase<StringType> 1 2 3 4 5 6 7 type Greeting = "Hello, world" type QuietGreeting = Lowercase <Greeting >type ASCIICacheKey <Str extends string > = `id-${Lowercase<Str>} ` type MainID = ASCIICacheKey <"MY_APP" >
将字符串中的每个字符转换为等效的小写字母 。
Capitalize<StringType> 1 2 3 type LowercaseGreeting = "hello, world" ;type Greeting = Capitalize <LowercaseGreeting >;
将字符串中的第一个字符转换为等效的大写字母 。
Uncapitalize<StringType> 1 2 3 type UppercaseGreeting = "HELLO WORLD" ;type UncomfortableGreeting = Uncapitalize <UppercaseGreeting >;
将字符串中的第一个字符转换为等效的小写字母 。
ReturnType<Type> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 declare function f1 ( ): { a : number ; b : string }; type T0 = ReturnType <() => string >;type T1 = ReturnType <(s: string ) => void >;type T2 = ReturnType <<T>() => T>;type T3 = ReturnType << T extends U, U extends number [] >() => T>; type T4 = ReturnType <typeof f1>;type T5 = ReturnType <any >;type T6 = ReturnType <never >;
构造一个由函数 Type 的返回类型 组成的类型。
ThisType<Type> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 type ObjectDescriptor <D, M> = { data?: D; methods?: M & ThisType <D & M>; }; function makeObject<D, M>( desc : ObjectDescriptor <D, M> ): D & M { let data : object = desc.data || {}; let methods : object = desc.methods || {}; return { ...data, ...methods } as D & M; } let obj = makeObject ({ data : { x : 0 , y : 0 }, methods : { moveBy (dx: number , dy: number ) { this .x += dx; this .y += dy; }, }, }); obj.x = 10 ; obj.y = 20 ; obj.moveBy (5 , 5 );
此实用程序不返回转换后的类型。 相反,它用作上下文 this 类型的标记。 请注意,必须启用 noImplicitThis 标志才能使用此实用程序。
InstanceType<Type> 1 2 3 4 5 6 7 8 9 10 class C { x = 0 ; y = 0 ; } type T0 = InstanceType <typeof C>;type T1 = InstanceType <any >;type T2 = InstanceType <never >;
构造一个由 Type 中构造函数的实例类型组成的类型。
ThisParameterType<Type> 1 2 3 4 5 6 7 8 9 function toHex (this : Number ) { return this .toString (16 ); } function numberToString ( n: ThisParameterType<typeof toHex> ) { return toHex.apply (n); }
提取函数类型的 this
参数的类型,如果函数类型没有 this
参数,则为未知。
OmitThisParameter<Type> 1 2 3 4 5 6 7 8 function toHex (this : Number ) { return this .toString (16 ); } const fiveToHex : OmitThisParameter <typeof toHex> = toHex.bind (5 ); console .log (fiveToHex ());
从 Type 中移除 this 参数。 如果 Type 没有显式声明此参数,则结果只是 Type。 否则,从 Type 创建一个不带此参数的新函数类型。 泛型被删除,只有最后一个重载签名被传播到新的函数类型中。
JSX JSX 介绍 JSX 规范是对 ECMAScript 的类似 XML 的语法扩展。
使用 .tsx
扩展名命名您的文件
启用 jsx
选项
不允许在 .tsx
文件中使用尖括号类型断言。
JSX 规范
as 运算符 1 2 3 4 const foo = <foo>bar;const foo = bar as foo;
as
运算符在 .ts
和 .tsx
文件中都可用,并且在行为上与尖括号 类型断言样式相同。
基于值的元素 1 2 3 4 import MyComponent from "./myComponent" ;<MyComponent /> ; <SomeOtherComponent /> ;
基于值的元素只是由范围内的标识符查找。
内在的元素 1 2 3 4 5 6 7 declare namespace JSX { interface IntrinsicElements { foo : any ; } } <foo />; <bar /> ;
<bar /> 没有在 JSX.IntrinsicElements 上指定。
1 2 3 4 5 declare namespace JSX { interface IntrinsicElements { [elemName : string ]: any ; } }
函数组件 1 2 3 4 5 6 7 8 9 10 11 12 13 interface FooProp { name : string ; X : number ; Y : number ; } declare function AnotherComponent (prop: { name: string } );function ComponentFoo (prop: FooProp ) { return <AnotherComponent name ={prop.name} /> ; } const Button = (prop: { value: string }, context: { color: string } ) => ( <button /> );
该组件被定义为一个 JavaScript 函数,其第一个参数是一个 props 对象。 TS 强制它的返回类型必须可分配给 JSX.Element。
函数组件重载 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 interface CeProps { children : JSX .Element [] | JSX .Element ; } interface HomeProps extends CeProps { home : JSX .Element ; } interface SideProps extends CeProps { side : JSX .Element | string ; } function Dog (prop:HomeProps ): JSX .Element ;function Dog (prop:SideProps ): JSX .Element ;function Dog (prop:CeProps ): JSX .Element { }
函数子组件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 interface MenuProps extends React .LiHTMLAttributes <HTMLUListElement > { ... };const InternalMenu = React .forwardRef <HTMLUListElement , MenuProps >((props, ref ) => ( <ul {...props } ref ={ref} /> )); type MenuComponent = typeof InternalMenu & { Item : typeof MenuItem ; SubMenu : typeof SubMenu ; }; const Menu : MenuComponent = InternalMenu as unknown as MenuComponent ;Menu .Item = MenuItem ;Menu .SubMenu = SubMenu ;<Menu.Item /> <Menu.SubMenu />
有效组件 1 2 3 4 5 6 7 8 9 10 11 12 13 declare namespace JSX { interface ElementClass { render : any ; } } class MyComponent { render ( ) {} } function MyFactoryFunction ( ) { return { render : () => {} }; } <MyComponent />; <MyFactoryFunction /> ;
元素实例类型必须可以分配给 JSX.ElementClass
,否则将导致错误。
1 2 3 4 5 6 class NotAValidComponent {}function NotAValidFactoryFunction ( ) { return {}; } <NotAValidComponent />; <NotAValidFactoryFunction /> ;
默认情况下,JSX.ElementClass
是 {},但可以对其进行扩展,以将 JSX
的使用限制为仅限于符合适当接口的类型。
类组件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 type Props = { header : React .ReactNode ; body : React .ReactNode ; }; class MyComponent extends React.Component <Props , {}> { render ( ) { return ( <div > {this.props.header} {this.props.body} </div > ); } } <MyComponent header={<h1 > Header</h1 > } body={<i > body</i > } />
泛型组件 1 2 3 4 5 6 type SelectProps <T> = { items : T[] };class Select <T> extends React .Component <SelectProps <T>, any > {}const Form = ( ) => <Select <string > items={['a' , 'b' ]} />;
函数组件 ref 1 2 3 4 5 6 7 8 9 10 11 12 import { FC , ForwardedRef , forwardRef, PropsWithRef } from "react" ;function InternalProgress (props: ProgressProps, ref?: ForwardedRef<HTMLDivElement> ) { return ( <div {...props } ref ={ref} > {props.children} </div > ) } export interface ProgressProps extends React .DetailedHTMLProps <React .HTMLAttributes <HTMLDivElement >, HTMLDivElement > {}export const Progress : FC <PropsWithRef <ProgressProps >> = forwardRef<HTMLDivElement >(InternalProgress )
组件 ‘as’ 属性 1 2 3 4 5 6 7 8 9 10 11 import React , { ElementType , ComponentPropsWithoutRef } from "react" ;export const Link = <T extends ElementType <any > = "a" >( props: { as ?: T; } & ComponentPropsWithoutRef<T> ) => { const Comp = props.as || "a" ; return <Comp {...props }> </Comp > ; }; <Link as ="div" > 文本</Link > ;
允许传入自定义 React
组件,或 div
, a
标签
组件作为 Props 传递 1 2 3 4 5 6 7 8 9 10 11 12 13 type RowProps = { element : React .ElementType <{ className?: string ; }>; } const Row = (props: RowProps ) => { return ( <props.element className ="h-8 w-8" /> ); }; <Row element ={ "div "} /> ;<Row element ={UserIcon} /> ;
各种各样的技巧 类型推导(infer) 1 2 3 4 type Capitalize <T extends string > = T extends `${infer U} ${infer V} ` ? `${Uppercase<U>} ${V} ` : T type capitalized = Capitalize <"hello world" >
也可以在 infer 中使用条件约束(extends
)
1 2 type SomeBigInt = "100" extends `${infer U extends bigint } ` ? U : never ;
keyof 取 interface 的键 1 2 3 4 5 6 7 8 9 10 interface Point { x : number ; y : number ; } type keys = keyof Point ;type Arrayish = { [n : number ]: unknown ; }; type A = keyof Arrayish ;
两个数组合并成一个新类型 1 2 3 4 5 6 7 8 9 10 const named = ["aqua" , "aquamarine" , "azure" ] as const ;const hex = ["#00FFFF" , "#7FFFD4" , "#F0FFFF" ] as const ;type Colors = { [key in (typeof named)[number ]]: (typeof hex)[number ]; };
索引签名 1 2 3 4 5 interface NumberOrString { [index : string ]: string | number ; length : number ; name : string ; }
只读元组类型 1 2 const point = [3 , 4 ] as const
从数组中提取类型 1 2 3 4 5 type Point = { x : number ; y : number ; }type Data = Point [];type PointDetail = Data [number ];
satisfies satisfies
允许将验证表达式的类型与某种类型匹配,而无需更改该表达式的结果类型。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 type Colors = 'red' | 'green' | 'blue' ;type RGB = [ red : number , green : number , blue : number ]; type Palette = Record <Colors , string | RGB >const palette : Palette = { red : [255 , 0 , 0 ], green : '#00ff00' , blue : [0 , 0 , 255 ], }; const redComponent = palette.red .at (0 );
使用 satisfies 1 2 3 4 5 6 7 8 const palette = { red : [255 , 0 , 0 ], green : '#00ff00' , blue : [0 , 0 , 255 ], } satisfies Record <Colors , string | RGB > const redComponent = palette.red .at (0 )
范型实例化表达式 不使用的情况下:
1 2 3 4 const errorMap : Map <string , Error > = new Map () type ErrorMapType = Map <string , Error >
使用泛型实例化表达式:
1 2 const ErrorMap = Map <string , Error >const errorMap = new ErrorMap ()
泛型实例化函数 1 2 3 function makeBox<T>(value : T) { return { value }; }
不使用:
1 2 3 4 5 6 function makeHammerBox (hammer: Hammer ) { return makeBox (hammer); } const makeWrenchBox : (wrench: Wrench ) => Box <Wrench > = makeBox;
使用:
1 2 const makeStringBox = makeBox<string >;makeStringBox (42 );
识别全局修改模块 1 2 3 4 5 6 7 8 declare global { interface String { fancyFormat (opts : FancyOption ): string ; } } export interface FancyOption { fancinessLevel : number ; }
获取数组元素的类型 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 const MyArray = [ { name : "Alice" , age : 15 }, { name : "Bob" , age : 23 }, { name : "Eve" , age : 38 }, ]; type Person = typeof MyArray [number ];type Age = typeof MyArray [number ]["age" ];type Age2 = Person ["age" ];
范型推导出列表字面量 1 2 3 4 5 6 7 8 9 10 11 12 const a = <T extends string >(t: T ) => t;const b = <T extends number >(t: T ) => t;const c = <T extends boolean >(t: T ) => t;const d = a ("a" ); const e = b (1 ); const f = c (true ); const g = <T extends string []>(t: [...T] ) => t; const h = g (["111" , "222" ]);
Object.keys 类型声明 1 2 3 4 5 6 7 const keys = Object .keys (options) as (keyof typeof options)[];keys.forEach (key => { if (options[key] == null ) { throw new Error (`Missing option ${key} ` ); } });
.d.ts 模版 Module: Plugin 例如,当您想使用扩展另一个库的 JavaScript 代码时
1 2 3 4 5 6 7 import { greeter } from "super-greeter" ;greeter (2 );greeter ("Hello world" );import "hyper-super-greeter" ;greeter.hyperGreet ();
“super-greeter
“ 的定义:
1 2 3 4 5 6 7 export interface GreeterFunction { (name : string ): void (time : number ): void } export const greeter : GreeterFunction ;
我们可以像下面这样扩展现有模块:
1 2 3 4 5 6 7 8 9 import { greeter } from "super-greeter" ;export module "super-greeter" { export interface GreeterFunction { hyperGreet (): void ; } }
全局库模板 Global .d.ts 全局库可能如下所示:
1 2 3 function createGreeting (s ) { return "Hello, " + s; }
或者像这样:
1 2 3 window .createGreeting = function (s ) { return "Hello, " + s; };
类型声明示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 declare function myLib (a: string ): string ;declare function myLib (a: number ): number ;interface myLib { name : string ; length : number ; extras?: string []; } declare namespace myLib { let timeout : number ; const version : string ; class Cat { constructor (n: number ); readonly age : number ; purr (): void ; } interface CatSettings { weight : number ; name : string ; tailLength?: number ; } type VetID = string | number ; function checkCat (c: Cat, s?: VetID ); }
Module: Function 1 2 3 import greeter from "super-greeter" ;greeter (2 );greeter ("Hello world" );
要处理通过 UMD
和模块导入:
1 2 3 4 5 6 7 export as namespace myFuncLib;/* 此声明指定该函数是从文件中导出的对象 */ export = Greeter ; /* 此示例说明如何为您的函数设置多个重载 */ declare function Greeter (name: string): Greeter .NamedReturnType ; declare function Greeter (length: number): Greeter .LengthReturnType ;
如果你也想从你的模块中公开类型,你可以把它们放在这个块中。 通常你会想要描述函数返回类型的形状; 如本例所示,应在此处声明该类型,请注意,如果您决定包含此命名空间,则模块可能会被错误地导入为命名空间对象,除非 --esModuleInterop
已打开: import * as x from '[~THE MODULE~]';
错误的!不要这样做!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 declare namespace Greeter { export interface LengthReturnType { width : number ; height : number ; } export interface NamedReturnType { firstName : string ; lastName : string ; } export const defaultName : string ; export let defaultLength : number ; }
Module: Class 例如,当您想要使用如下所示的 JavaScript
代码时:
1 2 3 const Greeter = require ("super-greeter" );const greeter = new Greeter ();greeter.greet ();
要处理通过 UMD
和模块导入:
1 2 3 4 5 6 7 8 9 export as namespace "super-greeter";/* 此声明指定类构造函数是从文件中导出的对象 */ export = Greeter ; /* 在此类中编写模块的方法和属性 */ declare class Greeter { constructor (customGreeting?: string ); greet : void ; myMethod (opts : MyClass .MyClassMethodOptions ): number ; }
如果你也想从你的模块中公开类型,你可以把它们放在这个块中,如果您决定包含此命名空间,则模块可能会被错误地导入为命名空间对象,除非 –esModuleInterop 已打开: import * as x from '[~THE MODULE~]';
错误的! 不要这样做!
1 2 3 4 5 6 declare namespace MyClass { export interface MyClassMethodOptions { width?: number ; height?: number ; } }
JSDoc 参考 @type 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 var s;var win;var promisedString;var elm = document .querySelector (selector);elm.dataset .myData = "" ; var ns;var jsdoc;var nas;var sb;var var9;var stringToNumber;var arrayLike;var sbn;var sbn2;var fn7;var fn6;var star;var question;var numberOrString = Math .random () < 0.5 ? "hello" : 100 ;var typeAssertedNumber = (numberOrString);let one = (1 );
导入类型 1 2 3 4 5 6 7 8 9 export type Pet = { name : string, }; function walk (p ) { console .log (`Walking ${p.name} ...` ); }
导入类型可以在类型别名声明中使用
1 2 3 4 5 6 var myPet;myPet.name ;
如果您不知道类型,或者如果它有一个很烦人的大类型,import types
可以用来从模块中获取值的类型:
1 2 3 4 var x = require ("./accounts" ).userAccount ;
@param 和 @returns 1 2 3 4 5 6 7 8 9 10 function stringsStrings (p1, p2, p3, p4 ) { }
同样,对于函数的返回类型:
1 2 3 4 5 6 7 8 9 function ps ( ) {} function ab ( ) {}
@typedef, @callback, 和 @param 1 2 3 4 5 6 7 8 9 10 11 12 var specialTypeObject;specialTypeObject.prop3 ;
您可以在第一行使用 object 或 Object
1 2 3 4 5 6 7 8 9 var specialTypeObject1;
@param 允许对一次性类型规范使用类似的语法。 请注意,嵌套的属性名称必须以参数名称为前缀:
1 2 3 4 5 6 7 8 9 10 11 function special (options ) { return (options.prop4 || 1001 ) + options.prop5 ; }
@callback 类似于 @typedef ,但它指定的是函数类型而不是对象类型:
1 2 3 4 5 6 7 8 9 const ok = (s ) => !(s.length % 2 );
当然,这些类型中的任何一种都可以在单行 @typedef 中使用 TypeScript 语法声明:
@template 您可以使用 @template 标记声明类型参数。 这使您可以创建通用的函数、类或类型:
1 2 3 4 5 6 7 8 9 10 11 12 function id (x ) { return x; } const a = id ("string" );const b = id (123 );const c = id ({});
使用逗号或多个标签来声明多个类型参数:
您还可以在类型参数名称之前指定类型约束。 只有列表中的第一个类型参数受到约束:
1 2 3 4 5 6 7 8 9 function seriousalize (key, object ) { }
最后,您可以为类型参数指定默认值:
1 2 3 4 5 6 7 class Cache { constructor (T ) { } } let c = new Cache ()
CLI 使用 CLI 1 2 3 4 5 6 7 8 9 10 11 12 $ tsc $ tsc index.ts $ tsc src/*.ts $ tsc --project tsconfig.production.json $ tsc index.js --declaration --emitDeclarationOnly $ tsc app.ts util.ts --target esnext --outfile index.js
编译器选项
:-
–
--all
boolean
显示所有编译器选项
--generateTrace
string
生成事件跟踪和类型列表
--help
boolean
提供有关 CLI 帮助的本地信息
--init
boolean
初始化 TypeScript 项目并创建 tsconfig.json 文件
--listFilesOnly
boolean
打印作为编译一部分的文件名,然后停止处理
--locale
string
设置来自 TypeScript 的消息传递语言。 这不影响发射
--project
string
编译项目给定其配置文件的路径,或带有 ‘tsconfig.json’ 的文件夹
--showConfig
boolean
打印最终配置而不是构建
--version
boolean
打印编译器的版本
构建选项
:-
–
--build
boolean
构建一个或多个项目及其依赖项(如果已过期)
--clean
boolean
删除所有项目的输出
--dry
boolean
显示将构建的内容(或删除,如果使用“–clean”指定)
--force
boolean
构建所有项目,包括那些看起来是最新的项目
--verbose
boolean
启用详细日志记录
监听选项
:-
–
--excludeDirectories
list
从监视进程中删除目录列表
--excludeFiles
list
从监视模式的处理中删除文件列表
--fallbackPolling
fixedinterval , priorityinterval , dynamicpriority , fixedchunksize
指定当系统用完本机文件观察器时观察器应使用的方法
--synchronousWatchDirectory
boolean
在本机不支持递归监视的平台上同步调用回调并更新目录监视程序的状态
--watch
boolean
观看输入文件
--watchDirectory
usefsevents , fixedpollinginterval , dynamicprioritypolling , _fixedchunksizepolling
指定在缺少递归文件监视功能的系统上如何监视目录
--watchFile
fixedpollinginterval , prioritypollinginterval , dynamicprioritypolling , fixedchunksizepolling , usefsevents , usefseventsonparentdirectory
指定 TypeScript 监视模式的工作方式
TSConfig Ref 可完成 90% 的任务 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 "compilerOptions" : { "esModuleInterop" : true , "skipLibCheck" : true , "target" : "es2022" , "verbatimModuleSyntax" : true , "allowJs" : true , "resolveJsonModule" : true , "moduleDetection" : "force" , "strict" : true , "noUncheckedIndexedAccess" : true , "moduleResolution" : "NodeNext" , "module" : "NodeNext" , "moduleResolution" : "Bundler" , "module" : "ESNext" , "noEmit" : true , "lib" : ["es2022" , "dom" , "dom.iterable" ], "lib" : ["es2022" ], "declaration" : true , "composite" : true , "sourceMap" : true , "declarationMap" : true }
顶层配置
:-
–
files
#
指定要包含
在程序中的文件的允许列表
extends
#
包含要继承
的另一个配置文件的路径
include
#
指定要包含
在程序中的文件名或模式数组
exclude
#
指定解析包含时应跳过
的文件名或模式数组
references
#
项目引用是一种将 TypeScript 程序构造成更小部分的方法
1 2 3 4 5 6 { "extends" : "./tsconfig" , "compilerOptions" : { "strictNullChecks" : false } }
类型检查(compilerOptions)
:-
–
allowUnreachableCode
#
允许无法访问的代码
allowUnusedLabels
#
允许未使用的标签
alwaysStrict
#
始终严格
exactOptionalPropertyTypes
#
启用后,TypeScript 应用更严格的规则来处理它如何处理类型或具有 ? 字首
noFallthroughCasesInSwitch
#
在 switch 语句中报告失败案例的错误
noImplicitAny
#
在某些不存在类型注释的情况下,TypeScript 将在无法推断类型时回退到变量的任何类型
noImplicitOverride
#
当处理使用继承的类时,子类可能与在基类中重命名时重载的函数“不同步”
noImplicitReturns
#
没有隐式返回
noImplicitThis
#
使用隐含的“any”类型在“this”表达式上引发错误
noPropertyAccessFromIndexSignature
#
此设置确保通过“点”(obj.key)语法访问字段和“索引”(obj[“key”])以及在类型中声明属性的方式之间的一致性
noUncheckedIndexedAccess
#
TypeScript 有一种方法可以通过索引签名来描述对象上具有未知键但已知值的对象
noUnusedLocals
#
报告未使用的局部变量的错误
noUnusedParameters
#
报告函数中未使用参数的错误
strict
#
严格标志启用了范围广泛的类型检查行为,从而更有效地保证了程序的正确性
strictBindCallApply
#
TypeScript 将检查函数调用、绑定和应用的内置方法是否使用底层函数的正确参数调用
strictFunctionTypes
#
此标志会导致更正确地检查函数参数
strictNullChecks
#
严格的空检查
strictPropertyInitialization
#
严格的属性初始化
useUnknownInCatchVariables
#
在 TypeScript 4.0 中,添加了支持以允许将 catch 子句中的变量类型从 any 更改为 unknown
模块(compilerOptions)
:-
–
allowUmdGlobalAccess
#
为 true 时,将允许你在模块文件中以全局变量的形式访问 UMD 的导出
baseUrl
#
可以让您设置解析非绝对路径模块名时的基准目录
module
#
设置程序的模块系统
moduleResolution
#
指定模块解析策略:’node’(Node.js)或 ‘classic’
moduleSuffixes
#
提供一种在解析模块时覆盖要搜索的默认文件名后缀列表的方法
noResolve
#
默认情况下,TypeScript 将检查导入和 <reference
指令的初始文件集,并将这些解析的文件添加到您的程序中
paths
#
一些将模块导入重新映射到相对于 baseUrl 路径的配置
resolveJsonModule
#
允许导入带有“.json”扩展名的模块,这是 node 项目中的常见做法
rootDir
#
默认: 所有输入的非声明文件中的最长公共路径
rootDirs
#
通过 rootDirs,你可以告诉编译器有许多“虚拟”的目录作为一个根目录
typeRoots
#
默认情况下,所有 可见 的 ”@types” 包都将包含在你的编译过程中
types
#
默认情况下,所有 可见 的 ”@types” 包都将包含在你的编译过程中
Emit(compilerOptions)
:-
–
declaration
#
为项目中的每个 TypeScript 或 JavaScript 文件生成 .d.ts 文件
declarationDir
#
提供一种配置发出声明文件的根目录的方法
declarationMap
#
为映射回原始 .ts 源文件的 .d.ts 文件生成源映射
downlevelIteration
#
降级是 TypeScript 的术语,用于转译到旧版本的 JavaScript
emitBOM
#
控制 TypeScript 在写入输出文件时是否会发出字节顺序标记 (BOM)
emitDeclarationOnly
#
只发出 .d.ts 文件;不要发出 .js 文件
importHelpers
#
对于某些降级操作,TypeScript 使用一些辅助代码来执行扩展类、展开数组或对象以及异步操作等操作
importsNotUsedAsValues
#
此标志控制导入的工作方式,有 3 个不同的选项: remove
, preserve
, error
inlineSourceMap
#
设置后,TypeScript 不会写出 .js.map 文件来提供源映射,而是将源映射内容嵌入到 .js 文件中
inlineSources
#
设置后,TypeScript 会将 .ts 文件的原始内容作为嵌入字符串包含在源映射中(使用源映射的 sourcesContent 属性)
mapRoot
#
指定调试器应该定位映射文件而不是生成位置的位置
newLine
#
指定发出文件时要使用的行尾顺序:“CRLF”(dos)或“LF”(unix)
noEmit
#
不要发出编译器输出文件,如 JavaScript 源代码、源映射或声明
noEmitHelpers
#
您可以在全局范围内为您使用的助手提供实现,并完全关闭助手函数的发出,而不是使用 importHelpers 导入助手
noEmitOnError
#
如果报告了任何错误,请不要发出编译器输出文件,如 JavaScript 源代码、源映射或声明
outDir
#
如果指定,.js(以及 .d.ts、.js.map 等)文件将被发送到此目录中
outFile
#
如果指定,所有全局(非模块)文件将连接到指定的单个输出文件中
preserveConstEnums
#
不要删除生成的代码中的 const enum 声明
preserveValueImports
#
在某些情况下,TypeScript 无法检测到您正在使用导入
removeComments
#
转换为 JavaScript 时从 TypeScript 文件中删除所有注释
sourceMap
#
启用源映射文件的生成
sourceRoot
#
指定调试器应定位 TypeScript 文件的位置,而不是相对源位置
stripInternal
#
不要为在其 JSDoc 注释中具有 @internal 注释的代码发出声明
完整性(compilerOptions)
:-
–
skipDefaultLibCheck
#
请改用 skipLibCheck
skipLibCheck
#
跳过声明文件的类型检查
编辑器支持(compilerOptions)
:-
–
disableSizeLimit
#
分配的内存量有一个上限。打开此标志将删除限制
plugins
#
可在编辑器内运行的语言服务插件列表
输出格式(compilerOptions)
:-
–
noErrorTruncation
#
不要截断错误消息
preserveWatchOutput
#
保留监视输出
pretty
#
使用颜色和上下文对错误和消息进行样式化,默认情况下启用
JavaScript 支持(compilerOptions)
:-
–
allowJs
#
允许 JavaScript 文件在你的工程中被引入,而不是仅仅允许 .ts 和 .tsx 文件
checkJs
#
与 allowJs 配合使用,当 checkJs 被启用时,JavaScript 文件中会报告错误
maxNodeModuleJsDepth
#
在 node_modules 下搜索和加载 JavaScript 文件的最大依赖深度
互操作约束(compilerOptions)
:-
–
allowSyntheticDefaultImports
#
允许合成默认导入
esModuleInterop
#
ES 模块互操作
forceConsistentCasingInFileNames
#
在文件名中强制使用一致的大小写
isolatedModules
#
隔离模块
preserveSymlinks
#
保留符号链接
编译器诊断(compilerOptions)
:-
–
diagnostics
#
用于输出调试信息
explainFiles
#
打印 TypeScript 视为项目一部分的文件的名称以及它们是编译一部分的原因
extendedDiagnostics
#
您可以使用此标志来发现 TypeScript 在编译时将时间花在哪里
generateCpuProfile
#
此选项使您有机会让 TypeScript 在编译器运行期间发出 v8 CPU 配置文件
listEmittedFiles
#
将编译过程中生成的文件的名称打印到终端
listFiles
#
打印编译部分文件的名称
traceResolution
#
当您尝试调试未包含模块的原因时
向后兼容性(compilerOptions)
:-
–
charset
#
在早期版本的 TypeScript 中,这控制了从磁盘读取文本文件时使用的编码
keyofStringsOnly
#
此标志将 keyof
类型运算符更改为返回 string
而不是 `string
noImplicitUseStrict
#
默认情况下,当向非 ES6 目标发出模块文件时,TypeScript 发出"use strict"
;文件顶部的序言。此设置禁用序言
noStrictGenericChecks
#
TypeScript 在比较两个泛型函数时会统一类型参数
out
#
请改用 outFile
suppressExcessPropertyErrors
#
抑制过多的属性错误
suppressImplicitAnyIndexErrors
#
抑制隐式任何索引错误
语言与环境(compilerOptions)
:-
–
emitDecoratorMetadata
#
发射装饰器元数据
experimentalDecorators
#
实验装饰器
jsx
#
控制 JSX 在 JavaScript 文件中的输出方式
jsxFactory
#
使用经典 JSX 运行时编译 JSX 元素时更改在 .js 文件中调用的函数
jsxFragmentFactory
#
指定在使用 jsxFactory 编译器选项指定 react JSX emit 时要使用的 JSX 片段工厂函数,例如 Fragment
jsxImportSource
#
声明模块说明符用于在将 jsx 用作 TypeScript 4.1 中引入的“react-jsx”或“react-jsxdev”时导入 jsx 和 jsxs 工厂函数
lib
#
TypeScript 包括一组默认的内建 JS 接口(例如 Math)的类型定义,以及在浏览器环境中存在的对象的类型定义(例如 document)
moduleDetection
#
模块检测
noLib
#
禁用自动包含任何库文件
reactNamespace
#
请改用 jsxFactory
target
#
现代浏览器支持全部 ES6 的功能,所以 ES6 是一个不错的选择
useDefineForClassFields
#
为类字段使用定义
项目(compilerOptions)
:-
–
composite
#
composite 选项会强制执行某些约束,使得构建工具(包括 在 –build 模式下的 TypeScript 本身)可以快速确定一个工程是否已经建立
disableReferencedProjectLoad
#
禁用引用项目加载
disableSolutionSearching
#
禁用解决方案搜索
disableSourceOfProjectReferenceRedirect
#
禁用源项目引用重定向
incremental
#
使 TypeScript 将上次编译的工程图信息保存到磁盘上的文件中
tsBuildInfoFile
#
这个选项可以让您指定一个文件来存储增量编译信息,以作为复合工程的一部分,从而可以更快的构建更大的 TypeScript 代码库
监听选项(watchOptions)
:-
–
watchFile
#
如何监视单个文件的策略
watchDirectory
#
在缺乏递归文件监视功能的系统下监视整个目录树的策略
fallbackPolling
#
使用文件系统事件时,此选项指定当系统用完本机文件观察器和/或不支持本机文件观察器时使用的轮询策略
synchronousWatchDirectory
#
在本机不支持递归监视的平台上同步调用回调并更新目录监视程序的状态
excludeDirectories
#
您可以使用 excludeFiles 来大幅减少在 –watch 期间监视的文件数量
excludeFiles
#
您可以使用 excludeFiles 从监视的文件中删除一组特定文件
1 2 3 4 5 { "watchOptions" : { "synchronousWatchDirectory" : true } }
类型采集(typeAcquisition)
:-
–
enable
#
提供用于在 JavaScript 项目中禁用类型获取的配置
include
#
如果您有一个 JavaScript 项目,其中 TypeScript 需要额外的指导来理解全局依赖关系,或者已通过 disableFilenameBasedTypeAcquisition 禁用了内置推理
exclude
#
提供用于禁用 JavaScript 项目中特定模块的类型获取的配置
disableFilenameBasedTypeAcquisition
#
TypeScript 的类型获取可以根据项目中的文件名推断出应该添加哪些类型
1 2 3 4 5 { "typeAcquisition" : { "enable" : false } }
另见