面试题答案
一键面试设计类型保护机制
- 基于属性检查:
- 在不同类型的用户对象中,定义一个能够区分用户类型的属性。例如,所有用户对象都有一个
userType
属性,值为'normal'
(普通用户)、'admin'
(管理员用户)、'vip'
(VIP用户)等。 - 在处理用户相关操作的函数中,通过检查这个属性来进行类型保护。比如:
interface NormalUser { userType: 'normal'; // 普通用户的其他属性和方法 name: string; age: number; } interface AdminUser { userType: 'admin'; // 管理员用户的其他属性和方法 name: string; age: number; managePermissions: string[]; } interface VIPUser { userType: 'vip'; // VIP用户的其他属性和方法 name: string; age: number; specialBenefits: string[]; } type User = NormalUser | AdminUser | VIPUser; function handleUser(user: User) { if (user.userType === 'admin') { // 这里user的类型被缩小为AdminUser console.log(user.managePermissions); } else if (user.userType === 'vip') { // 这里user的类型被缩小为VIPUser console.log(user.specialBenefits); } else { // 这里user的类型被缩小为NormalUser console.log(user.name); } }
- 在不同类型的用户对象中,定义一个能够区分用户类型的属性。例如,所有用户对象都有一个
- 基于函数检查:
- 可以定义类型谓词函数。例如:
function isAdminUser(user: User): user is AdminUser { return user.userType === 'admin'; } function handleUserWithPredicate(user: User) { if (isAdminUser(user)) { // 这里user的类型被缩小为AdminUser console.log(user.managePermissions); } else { // user的类型为NormalUser | VIPUser } }
避免代码冗余
-
提取公共逻辑:
- 如果不同类型用户有一些共同的操作逻辑,将这些逻辑提取到一个公共函数中。例如,所有用户都有登录操作,这个操作的逻辑可以提取出来:
function login(user: User) { console.log(`${user.name} logged in`); }
- 然后在处理不同类型用户的函数中调用这个公共函数。
-
使用继承或混入:
- 如果使用面向对象编程,可以利用继承来复用代码。例如,创建一个基类
UserBase
,包含一些通用的属性和方法,然后NormalUser
、AdminUser
和VIPUser
继承自这个基类。
class UserBase { name: string; age: number; constructor(name: string, age: number) { this.name = name; this.age = age; } commonFunction() { console.log('This is a common function for all users'); } } class NormalUser extends UserBase { userType: 'normal'; constructor(name: string, age: number) { super(name, age); this.userType = 'normal'; } } class AdminUser extends UserBase { userType: 'admin'; managePermissions: string[]; constructor(name: string, age: number, managePermissions: string[]) { super(name, age); this.userType = 'admin'; this.managePermissions = managePermissions; } }
- 另一种方式是使用混入(mixin),将一些功能模块混入到不同类型的用户对象中,以避免重复代码。
- 如果使用面向对象编程,可以利用继承来复用代码。例如,创建一个基类
-
使用模板字面量类型和映射类型(在TypeScript中):
- 例如,可以通过映射类型为不同类型用户生成相似的操作函数,减少重复代码。
type UserType = 'normal' | 'admin' | 'vip'; type UserPermissions = { normal: string[]; admin: string[]; vip: string[]; }; type UserOperation<T extends UserType> = { [K in T]: (user: { userType: K }) => void; }; const userOperations: UserOperation<UserType> = { normal(user) { console.log('Normal user operation'); }, admin(user) { console.log('Admin user operation'); }, vip(user) { console.log('VIP user operation'); } }; function performUserOperation(user: User) { userOperations[user.userType](user); }