Typescript面试题目回答
Typescript有哪些常用类型?
Typescript的常用类型包括:
- 基本类型:boolean(布尔类型)、number(数字类型)、string(字符串类型)。
- 特殊类型:null、undefined、void、never。
- 数组和元组:Array(数组类型)、Tuple(元组类型)。
- 枚举和任意类型:Enum(枚举类型)、Any(任意类型)。
- 对象类型:Object(对象类型),可以通过接口或类型别名来定义更具体的对象类型。
什么是TypeScript的对象类型?怎么定义对象类型?
在TypeScript中,对象类型用于表示具有多个属性的数据结构。可以通过字面量、接口或类型别名来定义对象类型。
- 字面量定义:直接在变量声明中指定对象的结构,例如:
let obj: { name: string; age: number } = { name: 'Alice', age: 30 };
- 接口定义:使用
interface
关键字定义对象的形状,例如:interface Person { name: string; age: number; }
,然后可以使用这个接口来声明变量:let person: Person = { name: 'Bob', age: 25 };
- 类型别名定义:使用
type
关键字为对象类型创建一个别名,例如:type Employee = { id: number; name: string; position: string };
,然后可以使用这个别名来声明变量:let employee: Employee = { id: 1, name: 'Charlie', position: 'Engineer' };
什么是TypeScript的类型别名?怎么定义类型别名?
类型别名是TypeScript中的一个功能,它允许你为复杂的类型表达式创建一个简洁的名称。这有助于提高代码的可读性和可维护性。
定义类型别名的语法是:type AliasName = Type;
。例如,可以为一个包含两个数字的对象类型定义一个别名:type Point = { x: number; y: number };
。然后可以使用这个别名来声明变量:let point: Point = { x: 10, y: 20 };
。
什么是TypeScript的接口?怎么定义接口?
接口是TypeScript中的一个核心概念,它用于定义对象的形状,即对象应该包含哪些属性以及这些属性的类型。接口还可以包含方法签名,用于描述对象应该实现哪些方法。
定义接口的语法是:interface InterfaceName { /* 属性和方法签名 */ };
。例如,可以定义一个表示人的接口:interface Person { name: string; age: number; greet(): void; }
。然后可以使用这个接口来声明一个类,该类实现了接口中定义的所有属性和方法:
class RealPerson implements Person { name: string; age: number; constructor(name: string, age: number) { this.name = name; this.age = age; } greet() { console.log(`Hello, my name is ${this.name}`); }
}
TypeScript的类型别名和接口有什么区别?
类型别名和接口在TypeScript中都可以用于定义对象的形状,但它们之间有一些关键的区别:
- 命名规范:类型别名的名称是唯一的,不能重复定义;而接口的名称可以重复,因为接口支持声明合并。
- 表示范围:类型别名可以表示任何类型,包括原始类型、联合类型、交叉类型和映射类型等;而接口只能表示对象类型。
- 互操作性:类型别名和接口可以相互扩展,但语法不同。类型别名可以使用
&
操作符来组合多个类型,而接口可以使用extends
关键字来继承另一个接口。
TypeScript中如何定义和导入模块?
在TypeScript中,可以使用ES模块或CommonJS模块系统来定义和导入模块。
- 定义模块:使用
export
关键字将函数、类、变量或类型导出为模块成员。例如:export const hello = () => { console.log('Hello, world!'); };
。 - 导入模块:使用
import
关键字从其他模块中导入成员。例如:import { hello } from './helloModule'; hello();
。
对于ES模块,TypeScript遵循ES6模块规范;对于CommonJS模块,TypeScript则使用Node.js的模块解析策略。
TypeScript的类有哪些成员可见性?
TypeScript的类成员具有三种可见性修饰符:
- public:成员在类的外部和内部都是可见的。这是默认修饰符。
- protected:成员在类的内部和派生类中是可见的,但在类的外部不可见。
- private:成员仅在类的内部可见,在类的外部和派生类中都不可见。
TypeScript的关键字static有什么作用?
static
关键字用于定义类的静态成员。静态成员是属于类的,而不是属于类的实例的。这意味着可以在不创建类实例的情况下访问静态成员。静态成员通常用于表示与类本身相关而不是与类的实例相关的数据或方法。
TypeScript类的readonly修饰符有什么作用?
readonly
修饰符用于定义类的只读属性。只读属性可以在类的构造函数中被初始化,但之后就不能再被修改了。这有助于保护类的状态不被意外改变。
TypeScript的void类型、object类型、never类型是什么?
- void类型:表示没有返回值的方法或函数的类型。当一个方法或函数不返回任何值时,可以将其返回类型指定为
void
。 - object类型:表示非原始类型的值,即除
null
和undefined
之外的所有类型的值。在TypeScript中,object
类型是所有非原始类型值的超类型。 - never类型:表示那些永不存在的值的类型。
never
类型通常用于表示函数永远不会正常返回的情况,例如函数内部总是抛出异常或进入无限循环。
TypeScript的Function类型是什么?
在TypeScript中,Function
类型表示一个函数。但是,通常更推荐使用箭头函数或具名函数签名来定义函数的类型,而不是直接使用Function
类型。因为Function
类型过于宽泛,它无法提供关于函数参数和返回值的类型信息。
TypeScript的any类型、unknown类型是什么?和any类型有什么区别?
- any类型:表示任意类型的值。在编译阶段,使用
any
类型的变量可以赋予任意类型的值,并且不会进行类型检查。这有助于在编写代码时提供更大的灵活性,但也会失去TypeScript提供的类型安全性。 - unknown类型:表示未知类型的值。与
any
类型不同,unknown
类型的值在赋值给另一个变量之前必须进行类型断言或类型检查。这有助于在编写代码时保持类型安全性,避免意外的类型错误。
与any
类型相比,unknown
类型更加安全,因为它要求在使用未知类型的值之前进行明确的类型检查。
TypeScript的关键字extends有什么作用?
extends
关键字在TypeScript中有两个主要用途:
- 类继承:用于定义一个类继承自另一个类。继承的类可以访问父类的属性和方法,并可以添加新的属性和方法或重写父类的方法。
- 接口继承:用于定义一个接口继承自另一个接口。继承的接口可以扩展父接口的属性和方法签名,并可以添加新的属性和方法签名。
TypeScript的关键字infer有什么作用?
infer
关键字是TypeScript中的高级类型操作之一,它用于在条件类型中推断类型。当使用条件类型时,如果需要根据某个条件来推断出一个类型,可以使用infer
关键字来声明一个占位符类型,并在条件满足时将其替换为实际的类型。
TypeScript的泛型是什么?
泛型是TypeScript中的一个强大功能,它允许在定义函数、接口或类时不具体指定类型,而是在使用时才指定类型。这有助于编写更加通用和可重用的代码。
例如,可以定义一个泛型函数来处理不同类型的数组:
function logArrayElements<T>(array: T[]): void { array.forEach(element => { console.log(element); });
}
在这个例子中,<T>
是一个类型参数,它表示函数将处理的数组元素的类型。在调用函数时,可以指定这个类型参数的具体值:
logArrayElements<number>([1, 2, 3]);
logArrayElements<string>(['Hello', 'World']);
TypeScript的索引访问类型、条件类型、映射类型是什么?
- 索引访问类型:允许通过索引来访问对象类型的属性类型。例如,如果有一个对象类型
Person
,可以使用Person['name']
来获取name
属性的类型。 - 条件类型:根据条件表达式的结果来选择不同的类型。条件类型的语法是
Type1 extends Type2 ? ResultType1 : ResultType2
。如果Type1
可以赋值给Type2
,则结果是ResultType1
,否则结果是ResultType2
。 - 映射类型:通过映射一个对象的所有属性来创建一个新的类型。映射类型的语法是
{ [P in K]: T }
,其中K
是属性名的类型(通常是字符串或数字索引类型),T
是属性值的类型。这可以用于将对象的所有属性转换为另一种类型,或者添加新的属性等。
TypeScript 的模板字面量类型
在 TypeScript 中,模板字面量类型是一种特殊的类型,它允许你通过模板字符串的方式来定义类型。模板字面量类型可以包含嵌入的表达式,这些表达式在类型检查的阶段会被求值。这种类型通常用于定义与字符串相关的类型,并且可以在类型定义中嵌入变量或类型运算。例如:
type Greeting = `Hello, ${string}`; // 定义一个模板字面量类型
const greeting: Greeting = "Hello, World"; // 正确
const wrongGreeting: Greeting = "Hi, World"; // 错误,不符合模板字面量类型的定义
TypeScript 的类型操作符 keyof
keyof
是 TypeScript 中的一个类型操作符,用于获取一个对象类型(或接口)的所有公共属性名组成的字符串字面量联合类型。它常用于类型安全的属性访问和映射类型的定义。例如:
interface Person { name: string; age: number;
} type PersonKeys = keyof Person; // "name" | "age"
TypeScript 的类型操作符 typeof
typeof
是 TypeScript 中的一个类型操作符,用于获取给定变量或表达式的类型,并返回一个表示该变量或表达式类型的字符串字面量。它常用于类型检查和类型映射。例如:
const num = 10;
type NumType = typeof num; // number
TypeScript 的内置工具类型 Awaited
Awaited
是 TypeScript 中的一个内置工具类型,用于取出 Promise 的返回值类型。它适合用在描述 then()
方法和 await
命令的参数类型时。例如:
type StringType = Awaited<Promise<string>>; // string
TypeScript 的内置工具类型 Partial
Partial
是 TypeScript 提供的一个内置工具类型,用于将对象类型中的所有属性变为可选属性。这在你只需要更新对象的部分属性时非常有用。例如:
interface Person { name: string; age: number;
} type PartialPerson = Partial<Person>; // { name?: string; age?: number; }
TypeScript 的内置工具类型 Required
Required
是 TypeScript 提供的一个内置工具类型,用于将对象类型中的所有属性设置为必需(非可选)。例如:
interface Person { name?: string; age?: number;
} type RequiredPerson = Required<Person>; // { name: string; age: number; }
TypeScript 的内置工具类型 Readonly
Readonly
是 TypeScript 提供的一个内置工具类型,用于将给定类型的所有属性设置为只读。这意味着新创建的类型将具有与原始类型相同的属性,但这些属性在新类型中是只读的,不可修改。例如:
interface Person { name: string; age: number;
} type ReadonlyPerson = Readonly<Person>; // { readonly name: string; readonly age: number; }
TypeScript 的内置工具类型 Pick
Pick
是 TypeScript 提供的一个内置工具类型,用于从对象类型中挑选出一个或多个属性,并创建一个包含这些属性的新类型。例如:
interface Person { name: string; age: number; address: string;
} type PersonPick = Pick<Person, "name" | "age">; // { name: string; age: number; }
TypeScript 的内置工具类型 Record
Record
是 TypeScript 提供的一个内置工具类型,用于创建一个对象类型,该对象的属性键是特定类型,属性值是另一种类型。例如:
type StringToNumber = Record<string, number>; // { [key: string]: number }
TypeScript 的内置工具类型 Exclude
Exclude
是 TypeScript 提供的一个内置工具类型,用于从联合类型中排除某些类型,并返回一个新的类型。例如:
type T1 = Exclude<'a' | 'b' | 'c', 'a'>; // 'b' | 'c'
TypeScript 的内置工具类型 Extract
Extract
是 TypeScript 提供的一个内置工具类型,用于从联合类型中提取与给定类型兼容的所有类型,并返回一个新的类型。它是 Exclude
的反向操作。例如:
type T1 = Extract<'a' | 'b' | 'c', 'a' | 'd'>; // 'a'
TypeScript 的内置工具类型 Omit
Omit
是 TypeScript 提供的一个内置工具类型,用于从对象类型中排除一个或多个属性,并创建一个包含剩余属性的新类型。它是 Pick
的反向操作。例如:
interface Person { name: string; age: number; address: string;
} type PersonOmit = Omit<Person, "address">; // { name: string; age: number; }
TypeScript 的内置工具类型 NonNullable
NonNullable
是 TypeScript 提供的一个内置工具类型,用于从类型中排除 null
和 undefined
,并返回一个新的类型。例如:
type T1 = NonNullable<string | null | undefined>; // string
TypeScript 的内置工具类型 Parameters
Parameters
是 TypeScript 提供的一个内置工具类型,用于获取一个函数类型的参数类型,并返回一个表示这些参数类型的元组。例如:
function foo(x: number, y: string): boolean { return x > 0 && y.length > 0;
} type FooParams = Parameters<typeof foo>; // [x: number, y: string]
TypeScript 的内置工具类型 ConstructorParameters
ConstructorParameters
是 TypeScript 提供的一个内置工具类型,用于获取一个构造函数的参数类型,并返回一个表示这些参数类型的元组。例如:
class MyClass { constructor(x: number, y: string) {}
} type MyClassParams = ConstructorParameters<typeof MyClass>; // [x: number, y: string]
TypeScript 的内置工具类型 ReturnType
ReturnType
是 TypeScript 提供的一个内置工具类型,用于获取一个函数类型的返回类型。例如:
function foo(): string { return "hello";
} type FooReturnType = ReturnType<typeof foo>; // string
TypeScript 的内置工具类型 InstanceType
InstanceType
是 TypeScript 提供的一个内置工具类型,用于获取一个构造函数类型的实例类型。例如:
class MyClass { name: string; constructor(name: string) { this.name = name; }
} type MyClassInstance = InstanceType<typeof MyClass>; // MyClass
注意:这里的 InstanceType
返回的应该是 MyClass
的实例类型,而不是 MyClass
本身。但在 TypeScript 的类型系统中,我们通常不需要显式地表示实例类型(因为它会自动推断),因此这里的描述主要是为了解释 InstanceType
的作用。在实际使用中,你可能会将 InstanceType
用于泛型约束或类型映射等场景。
TypeScript 的内置工具类型(Nolnfer、ThisParameterType、OmitThisParameter、ThisType)
- Nolnfer:这个类型在您的问题中可能是个拼写错误,我猜测您可能是想问
NonNullable
,上面已经介绍过了。 - ThisParameterType:
ThisParameterType
是 TypeScript 提供的一个内置工具类型,用于获取一个函数类型的this
参数的类型。这在处理类方法或需要明确this
类型的函数时非常有用。例如:
function foo(this: { bar: number }, x: string): number { return this.bar + x.length;
} type FooThisType = ThisParameterType<typeof foo>; // { bar: number }
- OmitThisParameter:这个类型在 TypeScript 的标准内置工具类型中并不存在。可能是您记错了某个类型或者看到了某个特定库中的扩展类型。在 TypeScript 中,没有直接的方式来“省略”
this
参数,因为this
参数的类型通常是由函数所在的上下文决定的。 - ThisType:
ThisType
是一个在 JSX 中使用的特殊类型,用于指定this
的类型。在普通的 TypeScript 代码中,你通常不需要使用ThisType
。但在 JSX 中,当你需要在回调函数中访问组件的实例时,可以使用ThisType
来指定this
的类型。例如:
interface MyComponentThisType { myMethod: () => void;
} const MyComponent = (props: {}) => { /* JSX code here */ return <button onClick={(e) => { // 在这里,`this` 被指定为 MyComponentThisType (this as MyComponentThisType).myMethod(); }}>Click me</button>;
} as React.FC<{}> & { this: ThisType<MyComponentThisType> };
注意:上面的 ThisType
示例是在 JSX 和 React 的上下文中使用的。在普通的 TypeScript 函数或类中,你通常不需要使用 ThisType
。
为什么要使用 TypeScript?TypeScript 有哪些常用特性?
why
- 静态类型检查:TypeScript使用静态类型,能在编译时进行类型检查,这有助于避免在运行时遇到类型相关的错误,从而提高代码的健壮性和稳定性。
- 提高代码可读性:通过类型注解和接口等特性,TypeScript能够清晰地描述代码的结构和数据的类型,使代码更易于阅读和理解。
- 便于重构和维护:对于大型、复杂的应用程序,TypeScript的类型系统使得重构代码变得更加容易,同时降低了维护成本。
- 支持现代JavaScript特性:TypeScript不仅包含了JavaScript的所有元素,还提供了最新的和不断发展的JavaScript特性,如异步功能和Decorators等,有助于建立健壮的组件。
- 提高开发效率:TypeScript提供了自动完成和动态输入等智能感知功能,这些功能能够大大提高开发人员的工作效率。
features
- 类型注解:为函数和变量添加约束的方式,使得代码在编译时就能进行类型检查。
- 接口:使用接口来描述一个拥有具体字段的对象,确保实现接口的对象包含了接口要求的结构。
- 类:TypeScript引入了“类”的概念,使得面向对象编程在JavaScript中得以实现。
- 枚举:枚举类型是对JavaScript标准数据类型的一个补充,使用枚举类型可以为一组数值赋予友好的名字。
- 模块:TypeScript支持模块的概念,可以把声明、数据、函数和类封装在模块中,避免全局命名空间污染,并方便管理依赖关系。
- 访问修饰符:TypeScript支持访问修饰符(public、private、protected),它们决定了类成员的可访问性,有助于封装和保护类的内部状态。
- 泛型:泛型允许在定义函数、接口或类时不指定具体类型,而是在使用时指定类型,这有助于编写更加灵活和可复用的代码。
- 类型断言:类型断言是一种告诉编译器“相信我,我知道自己在干什么”的方式,它允许开发人员将一个变量断言为特定类型,以便在编译时获得更好的类型检查。
具体讲解
- Typescript 有哪些常用类型?
- 什么是 TypeScript 的对象类型?怎么定义对象类型?
- 什么是 TypeScript 的类型别名?怎么定义类型别名?
- 什么是 TypeScript 的接口?怎么定义接口?
- TypeScript 的类型别名和接口有什么区别?
- TypeScript 中如何定义和导入模块?
- TypeScript 的类有哪些成员可见性?
- TypeScript 的关键字 static 有什么作用?
- TypeScript 类的 readonly 修饰符有什么作用?
- 什么是 TypeScript 的 void 类型?
- 什么是 TypeScript 的 object 类型?
- 什么是 TypeScript 的 never 类型?
- 什么是 TypeScript 的 Function 类型?
- 什么是 TypeScript 的 any 类型?
- 什么是 TypeScript 的 unknown 类型?和 any 类型有什么区别?
- TypeScript 的关键字 extends 有什么作用?
- TypeScript 的关键字 infer 有什么作用?
- 什么是 TypeScript 的泛型?
- 什么是 TypeScript 的索引访问类型?
- 什么是 TypeScript 的条件类型?
- 什么是 TypeScript 的映射类型?
- 什么是 TypeScript 的模板字面量类型?
- TypeScript 的类型操作符 keyof 有什么作用?
- TypeScript 的类型操作符 typeof 有什么作用?
- TypeScript 的内置工具类型 Awaited 有什么作用?
- TypeScript 的内置工具类型 Partial 有什么作用?
- TypeScript 的内置工具类型 Required 有什么作用?
- TypeScript 的内置工具类型 Readonly 有什么作用?
- TypeScript 的内置工具类型 Pick 有什么作用?
- TypeScript 的内置工具类型 Record 有什么作用?
- TypeScript 的内置工具类型 Exclude 有什么作用?
- TypeScript 的内置工具类型 Extract 有什么作用?
- TypeScript 的内置工具类型 Omit 有什么作用?
- TypeScript 的内置工具类型 NonNullable 有什么作用?
- TypeScript 的内置工具类型 Parameters 有什么作用?
- TypeScript 的内置工具类型 ConstructorParameters 有什么作用?
- TypeScript 的内置工具类型 ReturnType 有什么作用?
- TypeScript 的内置工具类型 InstanceType 有什么作用?
- TypeScript 的内置工具类型 Nolnfer 有什么作用?
- TypeScript 的内置工具类型 ThisParameterType 有什么作用?
- TypeScript 的内置工具类型 OmitThisParameter 有什么作用?
- TypeScript 的内置工具类型 ThisType 有什么作用?
- 为什么要使用 TypeScript?TypeScript 有哪些常用特性?