TypeScript中的联合类型赋值
有没有办法让这样的任务生效TypeScript中的联合类型赋值,typescript,Typescript,有没有办法让这样的任务生效 type A = { a: string }; type B = { b: string }; const x = { AA: undefined as A | undefined, BB: undefined as B | undefined, } const name1 = "AA" const x1 = x[name1]; // type: A | undefined x[name1] = x1; const name2 = "AA" as "AA
type A = { a: string };
type B = { b: string };
const x = {
AA: undefined as A | undefined,
BB: undefined as B | undefined,
}
const name1 = "AA"
const x1 = x[name1]; // type: A | undefined
x[name1] = x1;
const name2 = "AA" as "AA"|"BB";
const x2 = x[name2]; // type: A | B | undefined
x[name2] = x2; //ERROR
//Type 'A | B | undefined' is not assignable to type '(A & B) | undefined'.
// Type 'A' is not assignable to type 'A & B'.
// Property 'b' is missing in type 'A' but required in type 'B'.
这是由于最近在TypeScript 3.5中引入了一个功能(有关更多信息,请参阅),该功能提高了写入时的可靠性。简而言之,您所做的只是安全的,因为您碰巧知道您正在将一个值写回刚刚从中读取的属性。但是编译器没有意识到这一点,因为您有意将属性键的类型扩展为联合。因此,x2
的类型是A | B |未定义的
,将该类型写回x[name2]
:
const name2 = "AA" as "AA" | "BB";
let x2 = x[name2]; // type: A | B | undefined
x2 = { b: "okay" }; // works because x2 is of A | B | undefined
x[name2] = x2; // now this error makes sense, right?
在我看来,这里的问题是我所说的语言缺乏支持。您知道,A | B | undefined
类型的两个联合类型表达式x2
和x[name2]
不是相互独立的。它们要么都是A |未定义的
,要么都是B |未定义的
。但是编译器无法表达这种依赖性。这里的解决方法通常涉及泛型、类型断言或代码复制
泛型:让编译器理解这一点是安全的一种方法是对泛型函数进行抽象,其中名称是泛型类型,扩展了
“AA”|“BB”
:
但允许这样做比不允许更有用
断言:另一种解决方法是通过a松开赋值的
x
类型,如:
相当于
type L = {
a: string;
b: number | boolean;
c: number | boolean;
}
因此,如果我在赋值之前将{a:string;b:number;c:boolean}
类型的值加宽到L
,我就可以毫无怨言地将boolean
写入b
并将anumber
写入c
。当您执行这样的断言时,您需要小心不要对编译器撒谎,并将错误的值放在错误的属性中
重复:最后一个解决方法是手动引导编译器完成所有可能的操作。。。这是完全类型安全但冗余的:
const name5 = Math.random() < 0.5 ? "AA" : "BB";
if (name5 === "AA") {
const x5 = x[name5];
x[name5] = x5; // okay
} else {
const x5 = x[name5];
x[name5] = x5; // okay
}
const name5=Math.random()<0.5?“AA”:“BB”;
如果(名称5==“AA”){
常数x5=x[name5];
x[name5]=x5;//好的
}否则{
常数x5=x[name5];
x[name5]=x5;//好的
}
恐怕我没有一个很好的答案给你。TS3.5中改进的健壮性是100%正确的,并且确实捕获了bug,但也给开发人员带来了很多麻烦。通常我倾向于使用类型断言,因为它通常是实现目标的破坏性最小的更改 哦,好吧。希望有帮助!祝你好运
type Loosen<T extends object, K extends keyof T> = {
[P in keyof T]: P extends K ? T[K] : T[P]
};
(x as Loosen<typeof x, typeof name2>)[name2] = x2; // okay
type L = Loosen<{ a: string; b: number; c: boolean }, "b" | "c">;
type L = {
a: string;
b: number | boolean;
c: number | boolean;
}
const name5 = Math.random() < 0.5 ? "AA" : "BB";
if (name5 === "AA") {
const x5 = x[name5];
x[name5] = x5; // okay
} else {
const x5 = x[name5];
x[name5] = x5; // okay
}