TypeScript 要点

张开发
2026/4/13 9:19:03 15 分钟阅读

分享文章

TypeScript 要点
1.在项目中你都怎么使用TS的在我参与的项目中 ts还是非常重要的 帮助了代码的可维护性 开发效率 提供强大的类型系统和多种特性 常用的有:接口 interface, 类型别名type alias,泛型ganerics 和类型推导type inference1.基础类型 JavaScript数据类型2.接口 一般用来抽象对象的特性的 可以用类实现接口 和字面量定义对象3.类型别名4.泛型5.类型推导6.extends可以用来做 继承 泛型约束 条件类型 (infer结合 类型提取)typeScript 基础数据类型字符串(String) 数字(bumber) 布尔(boolean) 数组(Array) null nudefined symbol元组(Tuple):元组是固定长度的数组可以包含不同类型的元素。枚举(Enum):枚举是 TypeScript 中的一种特殊类型用于表示一组命名常数。空类型(void):用于函数没有返回值时指定其返回类型任意类型(any)用于函数没有返回值时指定其返回类型浏览器宿主对象(Date Math(慢服))接口Interfaceinterface 是 TypeScript 中用于定义对象结构的关键特性之一。它可以指定对象的属性、方法及其类型且可以通过扩展实现复用1.定义基本接口interface Person {​ name: string;​ age: number;​ }​ let user: Person {​ name: Alice,​ age: 30​ };2.可选属性: 使用 ? 来定义可选属性。interface Person {​ name: string;​ age?: number; // 可选属性​ }​ let user1: Person { name: Alice };3.只读属性: 使用 readonly(润德泥) 来定义只读属性确保它们不能被修改。interface Point {​ readonly x: number;​ readonly y: number;​ }​ const point: Point { x: 10, y: 20 };​ // point.x 5; // 错误x 是只读的4.函数类型: 可以通过接口来定义函数的类型。interface Greet {​ (name: string): string;​ }​ const greet: Greet (name) Hello, ${name};5.接口扩展: 接口支持继承可以扩展其他接口。interface Animal {​ name: string;​ }​ interface Dog extends Animal {​ breed: string;​ }​ let dog: Dog { name: Buddy, breed: Golden Retriever };类型别名Type Aliastype 关键字可以用于定义类型别名它可以给任何类型起一个名字可以是基础类型、联合类型、交叉类型等。1.基础类型别名:type StringOrNumber string | number;​ let value: StringOrNumber Hello;​ value 42;2.联合类型: 使用 | 来表示多个类型的联合。type Status success | error | loading;​ let currentStatus: Status success;3.交叉类型: 使用 来合并多个类型type Person { name: string; age: number };​ type Employee { company: string };​ type Worker Person Employee;​ const worker: Worker { name: Alice, age: 30, company: TechCo };4.字面量类型: 可以指定具体的值类型type Direction north | south | east | west;​ let direction: Direction north;泛型Generics泛型是 TypeScript 中的一个强大特性它允许你创建可以适用于多种类型的函数、接口或类使用类型参数的方式。泛型能够让类型变得更加灵活和可重用同时保持类型安全。1.泛型函数: 使用泛型来使函数支持不同类型的输入输出。function identityT(arg: T): T {​ return arg;​ }​ let result identity(42); // T 被推断为 number​ let result2 identity(Hello); // T 被推断为 string2.泛型接口: 使用泛型接口定义函数类型interface IdentityFnT {​ (arg: T): T;​ }​ const identity: IdentityFnnumber (arg) arg;3.泛型类: 泛型可以用于类定义允许类实例的类型在创建时指定。class BoxT {​ value: T;​ constructor(value: T) {​ this.value value;​ }​ }​ const box new Box(10); // T 被推断为 number4.泛型约束: 泛型还可以使用约束来限制它的类型。function getLengthT extends { length: number }(arg: T): number {​ return arg.length;​ }类型推导Type InferenceTypeScript 在大多数情况下可以自动推导出变量的类型而不需要显式声明类型。这减少了代码量提高了开发效率。1.基本类型推导let age 30; // TypeScript 会推导 age 的类型为 number​ let name Alice; // TypeScript 会推导 name 的类型为 string2.函数返回值类型推导: 如果函数返回值没有显式声明TypeScript 会根据返回值推导出类型。function add(a: number, b: number) {​ return a b; // TypeScript 推导出返回值类型为 number​ }3.数组和对象的推导: TypeScript 可以推导数组和对象的类型。let numbers [1, 2, 3]; // 推导为 number[]​ let person { name: Alice, age: 30 }; // 推导为 { name: string; age: number }extends 关键字extends 在 TypeScript 中有多个用法主要有以下几种​1.用于继承类在类之间使用 extends 关键字可以继承一个类的所有属性和方法class Animal {​ name: string;​ constructor(name: string) {​ this.name name;​ }​ speak() {​ console.log(${this.name} makes a sound);​ }​ }​ class Dog extends Animal {​ constructor(name: string) {​ super(name); // 调用父类的构造函数​ }​ speak() {​ console.log(${this.name} barks);​ }​ }​ ​ const dog new Dog(Buddy);​ dog.speak(); // 输出 Buddy bark2.用于泛型约束extends 可以用于约束泛型的类型确保泛型类型满足特定条件。这样可以确保泛型类型的安全性和正确性。function identityT extends string | number(value: T): T {​ return value;​ }​​ let a identity(Hello); // a 的类型是 string​ let b identity(42); // b 的类型是 number​ // let c identity(true); // 错误类型 boolean 不能赋给类型 string | number在这个例子中T extends string | number 约束了泛型类型 T 只能是 string 或 number 类型这避免了不符合条件的类型传入。3.用于条件类型extends 关键字还常常与条件类型结合使用用来根据类型进行不同的推导或处理。type IsStringT T extends string ? Yes : No;​ type Test1 IsStringstring; // Yes​ type Test2 IsStringnumber; // No在这个例子中T extends string 用来检查 T 是否为 string 类型。如果是 string则类型为 Yes否则类型为 No。4.与 infer 结合使用extends 与 infer 一起使用时可以在条件类型中提取和推断类型。type ExtractReturnTypeT T extends (...args: any[]) infer R ? R : never;​ type Func (a: number, b: number) string;​ type ReturnTypeOfFunc ExtractReturnTypeFunc; // ReturnTypeOfFunc 会被推导为 string在这个例子中T extends (...args: any[]) infer R 判断 T 是否是一个函数类型并使用 infer R 提取函数的返回类型。5.条件类型与 extends 的综合应用你可以通过组合条件类型和 extends 来实现更复杂的类型推导。例如下面的代码判断一个类型是否是 Function 类型并返回相应的类型type MyTypeT T extends Function ? Its a function : Its not a function;​ type Result1 MyType() void; // Its a function​ type Result2 MyTypestring; // Its not a functioninfer 关键字infer 是 TypeScript 中的一个高级特性主要用于条件类型中可以根据类型推断出一个子类型并将其赋给一个新的类型变量。infer 通常与条件类型extends结合使用允许你从某些类型中提取部分信息。type ReturnTypeOfT T extends (...args: any[]) infer R ? R : never;在这个例子中infer R 会自动推断出一个函数返回类型 R。如果 T 是一个函数类型R 就是该函数的返回类型否则返回 never。例子 1获取函数返回类型​假设你有一个函数并希望获取其返回值的类型你可以使用 infer 来实现​type ReturnTypeOfT T extends (...args: any[]) infer R ? R : never;​ function greet(name: string): string {​ return Hello, ${name};​ }​ type GreetReturnType ReturnTypeOftypeof greet; // GreetReturnType 会被推导为 string这里的 ReturnTypeOf 类型别名使用了 infer R 来提取 greet 函数的返回类型并将其赋值给 GreetReturnType所以 GreetReturnType 的类型是 string。例子 2从 Promise 中提取类型你可以使用 infer 来从 Promise 类型中提取 resolve 的类型type ResolvedTypeT T extends Promiseinfer R ? R : T;​ type ResolvedString ResolvedTypePromisestring; // ResolvedString 的类型是 string​ type ResolvedNumber ResolvedTypePromisenumber; // ResolvedNumber 的类型是 number在这个例子中ResolvedType 使用 infer R 来提取 Promise 中的类型。如果类型是 Promise它会提取出 resolve 时的值类型否则它会直接返回原始类型。总结​infer用于条件类型中从类型中推断出一个子类型可以提取出一个类型的部分结构或值类型。它通常和 extends 结合使用帮助我们在类型推导时提取出一些具体的类型信息​extends除了用来继承类外extends 在泛型和条件类型中也有广泛应用它用于约束泛型类型、实现条件类型判断或提取类型。通过 extends 和 infer 的组合TypeScript 可以实现更为灵活和强大的类型推导。类型断言在使用TypeScript的过程中你可能会遇到这种情况你比TypeScript更加清楚某个值的类型。 比如你从异步请求中拿到一个类型为any的值但你清楚的知道这个值就是string类型这个时候你可以通过类型断言1.尖括号语法 ()形式类型变量名let value: any this is a string; let length: number (stringvalue).length;2.as 语法形式变量名 as 类型let value: any this is a string; let length: number (value as string).length;非空断言当你明确知道某个值不可能为undefined和null时你可以用 在变量后面加上一个!function fun(value: string | undefined | null) { const str: string value; // error value 可能为 undefined 和 null const str: string value!; //ok const length: number value.length; // error value 可能为 undefined 和 null const length: number value!.length; //ok }确定赋值断言TypeScript的确定赋值断言允许在实例属性和变量声明后面放置一个!号从而告诉TypeScript该属性会被明确地赋值。let count!: number; initialize(); console.log(2 * count); // Ok function initialize() { count 10; }相关面试题1.typeScript 怎么在windows 下面挂载一个全局对象declare(低可蓝) global告诉 TS 这是全局类型声明declare global { interface Window { // 全局常量 APP_VERSION: string; // 全局对象 GLOBAL_CONFIG: { baseUrl: string; timeout: number; }; } }2.使用 type 和 interface 明确类型使用 interface 来定义对象的结构尤其适用于类和对象类型。​使用 type 来定义更复杂的类型例如联合类型、交叉类型、泛型等。interface User {​ id: number;​ name: string;​ }​ type ResponseT {​ data: T;​ success: boolean;​ };3.如何处理可空类型和undefined类型如何正确处理这些类型以避免潜在错误在TypeScript中可空类型是指一个变量可以存储特定类型的值也可以存储null或undefined可以声明使用联合类型 例如number | null或string | undefinedlet numberOrNull: number | null 10; numberOrNull null; // 可以赋值为null let stringOrUndefined: string | undefined Hello; stringOrUndefined undefined; // 可以赋值为undefined4.什么是联合类型和交叉类型联合类型表示一个值可以是多种类型中的一种而交叉类型表示一个新类型它包含了多个类型的特性。联合类型示例let myVar: string | number; myVar Hello; // 合法 myVar 123; // 合法交叉类型示例interface A { a(): void; } interface B { b(): void; } type C A B; // 表示同时具备 A 和 B 的特性5.什么是TypeScript中的声明文件声明文件通常以.d.ts扩展名结尾用于描述已有 JavaScript 代码库的类型信息。它们提供了类型定义和元数据以便在 TypeScript 项目中使用这些库时获得智能感知和类型安全。6.什么是类型断言类型断言允许程序员手动指定一个值的类型。这在需要明确告诉编译器某个值的类型时非常有用。let someValue: any this is a string; let strLength: number (someValue as string).length;7.TypeScript中的可选参数和默认参数是什么可选参数允许函数中的某些参数不传值在参数后面加上问号?表示可选。默认参数允许在声明函数时为参数指定默认值这样如果调用时未提供参数值则会使用默认值。可选参数示例function greet(name: string, greeting?: string) { if (greeting) { return ${greeting}, ${name}!; } else { return Hello, ${name}!; } }默认参数示例function greet(name: string, greeting: string Hello) { return ${greeting}, ${name}!; }8.类型守卫Type Guards是什么类型守卫是一种用于在运行时检查类型的技术它允许开发人员在特定的作用域内缩小变量的范围以确保正确推断类型。function isString(test: any): test is string { return typeof test string; } if (isString(input)) { // input 在此代码块中被收窄为 string 类型 }9.const和readonly的区别const主要用于声明常量值而readonly则用于标记类的属性使其只读。两者都不阻止对象内部属性被修改const用于声明常量值。一旦被赋值后其值将不能被重新赋值或修改。常量必须在声明时就被赋值并且该值不可改变。常量通常用于存储不会发生变化的值例如数学常数或固定的配置值。readonly关键字用于标记类的属性表明该属性只能在类的构造函数或声明时被赋值并且不能再次被修改。readonly属性可以在声明时或构造函数中被赋值但之后不能再被修改。readonly属性通常用于表示对象的某些属性是只读的防止外部代码修改这些属性的值。10.TypeScript中的this有什么需要注意的在TypeScript中与JavaScript相比this的行为基本上是一致的Typescript中箭头函数的 this 和 ES6 中箭头函数中的 this 是一致的。在TypeScript中当将noImplicit(因捕类谁特)This设置为true时意味着在函数或对象中使用this时必须显式声明this的类型noImplicitThis是TypeScript编译器的一个配置选项用于控制在函数或对象方法中使用this时的严格性。当将noImplicitThis设置为true时意味着必须显式声明this的类型否则会触发编译错误11.TypeScript中的静态类型和动态类型有什么区别静态类型是在编译期间进行类型检查可以在编辑器或 IDE 中发现大部分类型错误。动态类型是在运行时才确定变量的类型通常与动态语言相关联。12.TypeScript 中的模块化是如何工作的举例说明TypeScript 中使用 ES6 模块系统可以使用import和export关键字来导入和导出模块。可以通过export default导出默认模块在导入时可以使用import moduleName from modulePath。13. 如何约束泛型参数的类型范围可以使用泛型约束extends关键字来限制泛型参数的类型范围确保泛型参数符合某种特定的条件。interface Lengthwise { length: number; } function loggingIdentityT extends Lengthwise(arg: T): T { console.log(arg.length); return arg; } loggingIdentity({length: 10, value: 3}); // 参数满足 Lengthwise 接口要求可以正常调用14.什么是泛型约束中的 keyof 关键字举例说明其用法。keyof是 TypeScript 中用来获取对象类型所有键属性名的操作符。可以使用keyof来定义泛型约束限制泛型参数为某个对象的键。function getPropertyT, K extends keyof T(obj: T, key: K) { return obj[key]; } let x { a: 1, b: 2, c: 3 }; getProperty(x, a); // 正确 getProperty(x, d); // 错误Argument of type d is not assignable to parameter of type a | b | c15. 什么是装饰器有什么作用如何在TypeScript中使用类装饰器装饰器是一种特殊类型的声明可以附加到类、方法、访问符、属性或参数上以修改其行为。在 TypeScript 中装饰器提供了一种在声明时定义如何处理类的方法、属性或参数的机制。function classDecoratorT extends { new(...args: any[]): {} }(constructor: T) { return class extends constructor { newProperty new property; hello override; }; } classDecorator class Greeter { property property; hello: string; constructor(m: string) { this.hello m; } } console.log(new Greeter(world)); // 输出 { property: property, hello: override, newProperty: new property }当有多个装饰器应用于同一个声明时比如一个类中的方法它们将按照自下而上的顺序应用。对于方法装饰器从顶层方法开始依次向下递归调用方法装饰器函数。16. 装饰器工厂是什么请给出一个装饰器工厂的使用示例装饰器工厂是一个返回装饰器的函数。它可以接受参数并根据参数动态生成装饰器。function color(value: string) { return function (target: any, propertyKey: string) { // ... 在此处使用 value 和其他参数来操作装饰目标 }; } class Car { color(red) brand: string; }

更多文章