【发布时间】:2019-10-03 22:48:45
【问题描述】:
这是做作的,但通常我可以将对象文字传递给函数并在泛型中捕获文字的值,即:
type Values<V> = {
a: V;
b: V;
};
function mapValues<V>(v: Values<V>): V {
return v as any; // ignore
}
const vn = mapValues({ a: 1, b: 2 }); // inferred number
const vs = mapValues({ a: '1', b: '2' }); // inferred string
根据我传递给 mapValues 的内容,vn 和 vs 都被正确推断为 number 或 string。
这甚至适用于索引类型:
function mapValues2<V>(v: { [key: string]: V }): V {
return v as any;
}
const v2n = mapValues2({ a: 1, b: 2 }); // inferred number
const v2s = mapValues2({ a: '1', b: '2' }); // inferred string
v 对象字面量知道它的值是 string/number(分别),我能够捕获推断的 V 并在返回类型中使用它。
但是,一旦我使用映射类型,即:
enum Foo {
a,
b,
}
function mapValues3<K, V>(o: K, v: { [key in keyof K]: V }): V {
return v as any;
}
const v3n = mapValues3(Foo, { a: 1, b: 2 }); // inferred unknown
const v3s = mapValues3(Foo, { a: '1', b: '2' }); // inferred unknown
这就像V 忘记了它是否是string/number(分别),我得到unknown 推断。
请注意,如果我明确输入 const v3n: number,那么它会起作用,但我想依靠类型推断来为我计算出 V。
我很困惑为什么将 [key: string] 从第二个 sn-p 更改为第三个 [key in keyof K] 会影响对象文字类型推断的 : V 侧的推断。
有什么想法吗?
【问题讨论】:
-
我不知道如何回答为什么它会失败,除了一般直觉认为
T从函数F<T>的推断越不可靠,F越复杂。我的建议是通过推断v的类型来简化推断,例如mapValues3<O, V extends Record<keyof O, unknown>>(o: O, v: V): V[keyof O];。 -
如果以上内容符合您的用例,我很乐意将其转化为答案。
-
@jcalz 哇,必须将其返回到我的实际/非人为用例,但它确实有效!谢谢!是的,如果你回答-ize,我会接受!
标签: typescript