面试题答案
一键面试使用类型断言和类型保护实现需求
- 类型保护:
- 可以使用
typeof
、instanceof
等操作符进行类型保护。例如,如果要提取的属性在对象上,并且已知对象可能是特定类型,可以这样做:
function extractProperty<T extends object, K extends keyof T>(value: unknown, key: K): T[K] | undefined { if (typeof value === 'object' && value!== null) { const obj = value as T; if (obj.hasOwnProperty(key)) { return obj[key]; } } return undefined; }
- 在上述代码中,首先通过
typeof value === 'object' && value!== null
确保value
是一个非空对象,这是一种类型保护。然后使用类型断言as T
将value
断言为T
类型,接着通过hasOwnProperty
进一步确保对象有要提取的属性,从而保证类型安全地提取属性。
- 可以使用
- 类型断言:
- 直接使用类型断言,例如:
function extractPropertyDirect<T extends object, K extends keyof T>(value: unknown, key: K): T[K] | undefined { const obj = value as T; return obj[key]; }
- 这种方式虽然简洁,但风险较大,因为没有在运行时对
value
是否真的是T
类型进行检查。
类型断言的局限性
- 运行时风险:类型断言只是在编译时告诉编译器某个值具有特定类型,并不会在运行时进行实际的类型检查。如果断言错误,可能会导致运行时错误,比如访问不存在的属性引发
TypeError
。 - 缺乏灵活性:当实际类型与断言类型不匹配时,代码会变得脆弱,难以维护和扩展。例如,在大型项目中,如果类型定义发生变化,没有经过严格检查的类型断言可能会导致整个功能出错。
替代方案
- 使用类型守卫函数:
- 可以编写一个自定义的类型守卫函数,它在运行时进行类型检查并返回一个布尔值,以表明值是否符合特定类型。
function isType<T>(value: unknown, check: (v: unknown) => value is T): value is T { return check(value); } function isMyType(value: unknown): value is { myProp: string } { return typeof value === 'object' && value!== null &&'myProp' in value && typeof (value as { myProp: string }).myProp ==='string'; } function extractMyProp(value: unknown) { if (isType(value, isMyType)) { return value.myProp; } return undefined; }
- 使用
in
操作符结合类型保护:- 如前面代码中使用
hasOwnProperty
一样,in
操作符可以在运行时检查对象是否有某个属性,结合类型保护(如typeof
检查对象类型),可以更安全地提取属性。这比直接类型断言更具健壮性,因为它在运行时进行了属性存在性的检查。
- 如前面代码中使用