【发布时间】:2021-06-05 17:04:45
【问题描述】:
考虑以下代码:
interface Wrap<Value> {
pick(): Value
}
class WrapConstant<Value> implements Wrap<Value> {
constructor(public readonly a: Value) { }
pick(): Value { return this.a }
}
type Unwrap<Wrapped> = { [P in keyof Wrapped]: Wrapped[P] extends Wrap<infer Value> ? Value : never }
class WrapTuple<Tuple extends Wrap<unknown>[], Value = Unwrap<Tuple>> implements Wrap<Value> {
readonly ts: Tuple
constructor(...t: Tuple) { this.ts = t }
pick(): Value { return this.ts.map(a => a.pick()) } // fails to type check
}
type T1 = Unwrap<[WrapConstant<number>, WrapConstant<string>]> // [number, string]
new WrapTuple(new WrapConstant(1), new WrapConstant("hello")).pick() // [1, "hello"]
基本上我正在解开一个我知道遵循某种形状的元组(Wrap<Values> 的元组)。 WrapTuple 中的 pick() 函数应该保证返回相同形状的未包装类型(由 Unwrap<Tuple> 提供),尽管我在该行中遇到类型检查错误。问题:
- 这是因为
Unwrap<Tuple>不能保证由于条件类型推断而具有相同的形状吗? - 是否可以在不强制转换
as unknown as Value的情况下使其工作?
更新:正如 Linda 所说,映射元组不会产生元组。我尝试按照here的建议合并我自己的地图声明:
interface Array<T> {
map<U>(callbackfn: (value: T, index: number, array: T[]) => U,
thisArg?: any): { [K in keyof this]: U }
}
但这仍然需要将map 断言为Value:
pick(): Value { return this.ts.map(a => a.pick()) as Value }
【问题讨论】:
-
.map总是会失败类型检查,因为它返回一个可变长度的数组而不是一个元组。 -
没错,
map永远不会返回元组,因为它在可变数组上运行
标签: typescript tuples type-inference variadic-tuple-types