Typescript
TypeScript 相关面试问题
1. TypeScript 的优势
- 继承了 JavaScript 的所有语法特性,JS 代码可在 TS 环境很好的运行
- 增加了静态类型,可以在编写代码时检查语法错误,减少运行时的错误,使得代码质量更好,更健壮
- 类型可以一定程度上充当文档
- 编辑器自动填充、自动联想、智能提示和语法错误检查
2. interface 与 type 的区别
-
语法和使用
interface主要用于定义对象的结构的类型type不仅可以用于定义对象的结构,还可以用于其他类型(例如:基础类型、联合类型、交叉类型)
-
扩展
interface支持扩展(继承),可以通过extends进行继承type通过交叉类型(&)进行扩展
-
重复声明
interface可以重复声明,并且会自动合并type不能重复声明,重复时会报错
3. any、void、never、unknown
- any:任意类型,相当于放弃了类型校验
- void:没有任何类型(函数没有返回值时使用)
- never:不可能存在的值(返回 never 的函数必须存在无法达到的终点)
- unknown:暂时不确定是什么类型(当你暂时不知道是什么数据类型但需要往下进行时,或者因为逻辑分支产生不同数据类型的结果时,暂时定义为 unknown)
4. 联合类型
定义:当一个变量的类型是多种类型中的其中一种时,通过使用 | 可以将多个类型组合在一起。
注意:当一个变量是联合类型时,只能访问联合类型的所有类型都拥有的属性或方法。
function printValue(value: number[] | string) {
// 此处只能使用数组和字符串都存在的属性和方法
console.log(value.length)
if (typeof value === 'string') {
value.toUpperCase() // 此处可以使用字符串的所有属性和方法
} else {
value.push(1) // 此处可以使用数组的所有属性和方法
}
}
5. 交叉类型
定义:交叉类型是 TypeScript 中用于将多个类型合并成一个新类型。
注意:如果参与交叉的类型中有同名属性且类型不同,交叉类型将会导致错误。
type Person = {
name: string;
};
type Employee = {
employeeId: number;
};
// 交叉类型,表示必须同时拥有 Person 和 Employee 的属性
type Worker = Person & Employee;
const worker: Worker = {
name: "Alice",
employeeId: 1234
};
6. 泛型
定义:泛型允许在定义函数、接口时将类型参数化,而不必预先指定具体的类型。可以理解为类型的形参,在调用函数或者接口时再传入具体的类型。
例如 React 中的 useState 就是一个泛型函数,在调用函数时传入变量的具体类型。
// 调用 useState 时传入 number[] 类型, 通知 useState 参数是一个 number 类型的数组
const [arr, setArr] = useState<number[]>([])
7. 内置泛型
7.1. Pick<T, K>
Pick<T, K> 从某个类型 T 中挑选出一部分属性 K,构成一个新的类型。
interface User {
id: number;
name: string;
age: number;
}
// Pick 只挑选 id 和 name
const user4: Pick<User, "id" | "name"> = {
id: 1,
name: "Alice"
};
7.2. Omit<T, K>
Omit<T, K> 与 Pick 相反,它从某个类型 T 中排除指定的属性 K,构成一个新的类型。
interface User {
id: number;
name: string;
age: number;
}
// Omit 去掉 age 属性
const user5: Omit<User, "age"> = {
id: 2,
name: "Bob"
};
7.3. Partial<T>
Partial<T> 用于将某个类型的所有属性变为可选的。
interface User {
id: number;
name: string;
age: number;
}
// Partial 将所有属性变为可选
const user1: Partial<User> = {
name: "Alice"
};
7.4. Required<T>
Required<T> 将某个类型的所有可选属性变为必选(required)。
interface User {
id?: number;
name?: string;
age?: number;
}
// Required 将所有属性变为必选
const user2: Required<User> = {
id: 1,
name: "Alice",
age: 30
};
7.5. Readonly<T>
Readonly<T> 将某个类型的所有属性变为只读的(readonly),使得这些属性不能被修改。
interface User {
id: number;
name: string;
}
// Readonly 将所有属性变为只读
const user3: Readonly<User> = {
id: 1,
name: "Bob"
};
// user3.id = 2; // 错误,id 属性是只读的
7.6. Record<K, T>
Record<K, T> 构造一个对象类型,其属性名为类型 K 的联合类型,属性值为类型 T。常用于将某些类型映射到另一个类型。
type Role = "admin" | "user" | "guest";
// Record 用于将 Role 映射到 boolean 值
const roles: Record<Role, boolean> = {
admin: true,
user: false,
guest: false
};
7.7. Exclude<T, U>
Exclude<T, U> 从类型 T 中排除那些可以赋值给类型 U 的属性。常用于过滤掉某些不需要的类型。
type Status = "success" | "error" | "pending";
// Exclude 去除 "error" 类型
type SuccessOrPending = Exclude<Status, "error">;
7.8. Extract<T, U>
Extract<T, U> 提取类型 T 中可以赋值给类型 U 的属性,常用于保留某些需要的类型。
type Status = "success" | "error" | "pending";
// Extract 提取 "success" 和 "pending"
type ValidStatus = Extract<Status, "success" | "pending">;
7.9. NonNullable<T>
NonNullable<T> 从类型 T 中排除 null 和 undefined。
type MaybeString = string | null | undefined;
// NonNullable 去掉 null 和 undefined
type StrictString = NonNullable<MaybeString>;
7.10. ReturnType<T>
ReturnType<T> 用于获取函数类型 T 的返回类型。
function getUser() {
return { id: 1, name: "Alice" };
}
// ReturnType 获取函数的返回类型
type UserReturnType = ReturnType<typeof getUser>;
8. keyof 和 typeof 关键字的作用?
keyof返回对象类型中的所有 key 组成的联合类型typeof获取一个变量或对象的类型