Ray*_*han 5 javascript typescript
我想将键和值动态映射list到obj. 但是,TS 给了我一条错误消息:
Type 'string | number' is not assignable to type 'never'
我不知道出了什么问题。下面是代码片段:
interface T {
// uncomment the next line makes the error go away
// [k: string]: any
a: string;
b?: string;
c?: number;
}
const obj: T = {
a: 'something',
};
const list: Array<{
foo: keyof T;
bar: string | number;
}> = [
{ foo: 'b', bar: 'str' },
{ foo: 'c', bar: 1 },
];
list.forEach(item => {
const { foo, bar } = item;
// The error message comes from the next line
obj[foo] = bar;
});
Run Code Online (Sandbox Code Playgroud)
我注意到,如果我将输入[k: string]: any包含在 中interface T,错误消息就会消失。
但是,我不愿意这样做,因为我可以将其他键/值对添加到 中obj,例如obj.d = 'error'没有 TS 警告我。
另外,我很好奇为什么 TS 会给我这个错误消息,以及类型never是什么。
对于tsconfig.json,我通过运行使用默认值tsc --init与version 3.5.1
谢谢你。
TypeScript 3.5 关闭了一个漏洞,即未正确检查键联合上的索引访问写入。如果我有一个objtype的对象T和一个foo泛型 type的键keyof T,那么虽然您可以安全地从,like读取类型的属性,但编写这样的属性可能不安全,例如 在您的代码中,可能是,也可能是,这样写是不安全的。T[keyof T]obj[foo]const baz: T[keyof T] = obj[foo]const bar: T[keyof T] = ...; obj[foo] = bar;foo"a"bar1
漏洞被关闭的方式:如果我从键的联合中读取一个值,它会变成属性类型的联合,就像以前一样。但如果我写一个值到键的结合,它成为一个路口物业类型。所以说我有一个o类型的对象,{a: string | number, b: number | boolean}我想写一些东西o[Math.random()<0.5 ? "a" : "b"]......写什么是安全的?只有一些东西,适用于既 o.a 和 o.b......也就是(string | number) & (number | boolean),这(当你穿过十字路口分发工会和减少小提琴)变得只number。您只能安全地编写一个number.
但是,在您的情况下,交集是string & string & number。不幸的是,没有既是 astring又是 a number... 的值,所以它被简化为never. 哎呀。
为了解决这个问题,我可能会重构这段代码,使其list类型更窄,只允许“匹配”foo和bar属性,然后将forEach方法传递给通用回调,其中foo和bar被注释,以便obj[foo]和bar被视为相同的类型:
type KV = { [K in keyof T]-?: { foo: K, bar: NonNullable<T[K]> } }[keyof T]
/* type KV = {
foo: "a";
bar: string;
} | {
foo: "b";
bar: string;
} | {
foo: "c";
bar: number;
} */
const list: Array<KV> = [
{ foo: 'b', bar: 'str' },
{ foo: 'c', bar: 1 },
];
list.forEach(<K extends keyof T>(item: { foo: K, bar: NonNullable<T[K]> }) => {
const { foo, bar } = item;
obj[foo] = bar; // okay
});
Run Code Online (Sandbox Code Playgroud)
该KV类型对映射和查找类型进行了一些类型处理,以生成所有可接受foo/bar对的联合,您可以通过在KV定义上使用 IntelliSense 进行验证。
并且forEach()回调作用于item: { foo: K, bar: NonNullable<T[K]> }generic类型的值K extends keyof T。Soobj[foo]将被视为 type T[K],您将为其分配 a NonNullable<T[K]>,根据不太合理但足够方便的规则,这是可以接受的。
那有意义吗?希望有所帮助;祝你好运!
| 归档时间: |
|
| 查看次数: |
2021 次 |
| 最近记录: |