我有一个存储一组区分的联合类型的类型:
type M = {
foo: {a: "foo"};
bar: {a: "bar"};
};
现在我想创建一个函数,根据它的参数构造并返回正确类型的实例,比如:
const a1 = f1("foo"); // {a: "foo"}
const b1 = f1("bar"); // {a: "bar"}
但看似简单的正向类型赋值未通过类型判断:
function f1<T extends keyof M>(a: T): M[T] {
return {a};
/*
Type '{ a: keyof M; }' is not assignable to type 'M[T]'.
Type '{ a: keyof M; }' is not assignable to type 'never'.
The intersection '{ a: "foo"; } & { a: "bar"; }' was reduced
to 'never' because property 'a' has conflicting types in some
constituents.(2322)
*/
}
然而,如果我这样做,它就会工作(我仍然需要创建new个实例,所以它对我没有帮助):
const v = {
foo: {a: "foo" as const},
bar: {a: "bar" as const},
};
type V = typeof v;
function f2<T extends keyof V>(a: T): V[T] {
return v[a]; // no problem!
}
const a2 = f2("foo"); // {a: "foo"}
const b2 = f2("bar"); // {a: "bar"}
即使类型V
与上面的类型M
相同.
让它更令人困惑的是,这一点也失败了:
const c = {
foo: {x: {a: "foo" as const}},
bar: {x: {a: "bar" as const}},
};
function f<T extends keyof M>(a: T): M[T] {
return c[a].x;
/*
Type '{ a: "foo"; } | { a: "bar"; }' is not assignable to type
'M[T]'.
Type '{ a: "foo"; }' is not assignable to type 'M[T]'.
Type '{ a: "foo"; }' is not assignable to type 'never'.
The intersection '{ a: "foo"; } & { a: "bar"; }' was reduced
to 'never' because property 'a' has conflicting types in
some constituents.(2322)
*/
}
为什么TS会在第一个和第三个示例中try 与所有并集类型相交,而不是在第二个示例中?我是不是遗漏了什么?有没有办法让它发挥作用?