面试题答案
一键面试- TypeScript上下文类型推导处理:
- 函数
combine
定义了类型参数T
约束为具有a
属性且类型为number
的对象类型。 - 当使用
combine(arrA, arrB)
时,TypeScript 会尝试根据arrA
和arrB
的类型来推导T
的具体类型。 arrA
的元素类型为{ a: number; b: string }
,arrB
的元素类型为{ a: number; c: string }
。TypeScript 会寻找一个能同时兼容这两个数组元素类型的T
,它会取两者共有的属性a
,并将T
推导为{ a: number }
。
- 函数
- 类型兼容性问题:
- 因为
T
被推导为{ a: number }
,而arrA
中的元素有额外的b
属性,arrB
中的元素有额外的c
属性。在合并后的数组中,这些额外属性可能会丢失。例如,如果函数内部只是简单地合并数组,返回的数组元素类型为{ a: number }
,像arrA[0].b
这样的访问在类型检查时会报错,因为{ a: number }
类型没有b
属性。
- 因为
- 解决方法:
- 使用交叉类型:
- 可以定义一个新类型,它是
arrA
和arrB
元素类型的交叉类型。
type CombinedType = { a: number } & ({ b: string } | { c: string }); function combine<T extends CombinedType>(arr1: T[], arr2: T[]): T[] { return arr1.concat(arr2); } const arrA = [{ a: 1, b: 'test1' }, { a: 2, b: 'test2' }]; const arrB = [{ a: 3, c: 'test3' }]; const result = combine<CombinedType>(arrA, arrB);
- 可以定义一个新类型,它是
- 放宽类型约束:
- 如果可以接受丢失额外属性的情况,可以直接使用更宽泛的类型定义
combine
函数。
function combine<T extends { a: number }>(arr1: T[], arr2: T[]): T[] { return arr1.concat(arr2); } const arrA = [{ a: 1, b: 'test1' }, { a: 2, b: 'test2' }] as { a: number }[]; const arrB = [{ a: 3, c: 'test3' }] as { a: number }[]; const result = combine(arrA, arrB);
- 这里将
arrA
和arrB
类型断言为{ a: number }[]
,这样虽然丢失了额外属性的类型信息,但能满足combine
函数的类型约束。不过这种方法可能会导致运行时访问不存在属性的错误,需要谨慎使用。
- 如果可以接受丢失额外属性的情况,可以直接使用更宽泛的类型定义
- 使用交叉类型: