关闭 strictNullChecks 的 Typescript 索引访问
Typescript index access with strictNullChecks turned off
以下代码在启用 strictNullChecks
时有效。
interface IData {
a: number;
b: string;
}
const data: Partial<IData> = {};
// I am doing "as const" to make 'a' and 'b' string literal
// keys of IData. In the real code, these keys would come from elsewhere.
for (const key of ['a', 'b'] as const) {
data[key] = undefined;
}
console.log(data);
flag关闭时报错:
Type 'any' is not assignable to type 'never'.(2322)
为什么?
有没有办法在不启用 strictNullChecks
或使用 any
的情况下克服这个问题?
也许你想要
interface IData {
a: number;
b: string;
}
const data: Partial<IData> = {};
for (const key of ['a', 'b']) {
data[key] = null;
}
console.log(data);
但根据 Calz 的评论,不太清楚您的用例是什么
当 the --strictNullChecks
compiler option is off, but I have not found an existing issue in GitHub about it. It is almost universally recommended 开启 --strictNullChecks
时,这似乎是 TypeScript 的限制,因此 [=120] 中的覆盖率几乎没有=] 以及有关关闭时的行为方式的文档。
我这里的分析是有几个东西交互不佳:
当 --strictNullChecks
关闭时,null
和 undefined
被认为可分配给 几乎 任何类型。这几乎使他们bottom types like the never
type。但是,无论出于何种原因,它们 不能 分配给 never
类型。这是一个关键的区别(我可能认为这是一个错误或限制)。只有 never
可分配给 never
:
declare let never: never;
declare let any: any;
declare let v: never;
v = undefined; // error!
v = null; // error
v = any; // error
v = never; // okay
当--strictNullChecks
关闭时,null
和undefined
被吸收到unions(如never
):
type Foo = string | undefined;
// type Foo = string
当您尝试为联合类型的 key
赋值给 obj[key]
时,TypeScript 要求该值可赋给 intersection of the value types for each key in the union, as implemented in microsoft/TypeScript#30769:
interface Bar {
x: number | string;
y: string | boolean;
}
const bar: Bar = { x: 3, y: true };
for (const key of ['x', 'y'] as const) {
bar[key] = 1; // error! number is not assignable to string
bar[key] = "okay"; // okay
}
综合起来:
在此代码中:
for (const key of ['a', 'b'] as const) {
data[key] = undefined;
}
因为 data
是 Partial<IData>
类型,--strictNullChecks
在 上,这个交集将是 (number | undefined) & (string | undefined)
,计算结果为只是 undefined
。因此,当 key
仅已知为 "a"
或 [=39 时,undefined
是您可以分配给 data[key]
的唯一安全值=].上面的赋值编译没有错误。
但是如果 --strictNullChecks
关闭 ,(number | undefined) & (string | undefined)
会崩溃为 number & string
,也就是 never
。并且 undefined
无论出于何种原因,都不能分配给 never
。上面的作业给了你你所面临的错误。
废话。
那么,您可以如何进行?假设您不想打开 --strictNullChecks
(这也是几乎普遍推荐的),并且您不想提交 issue in GitHub about it (which would probably end up being marked as "Working as Intended" or "Design Limitation", but maybe possibly would be marked as "Bug" which would be low on anyone's priority list to fix), then you can work around it via type assertion。您可以只说“undefined
可分配给 never
此处”,编译器将接受它:
for (const key of ['a', 'b'] as const) {
data[key] = undefined as never; // okay
}
这种类型安全吗?好吧,当 --strictNullChecks
关闭时,它的类型安全性并不比 undefined
的任何其他处理低。类型断言本质上让你做不安全的事情,所以你 从编译器那里承担一些安全责任。但不幸的是,你在这里能做的也好不了多少。
(好吧,你知道的,除了打开 --strictNullChecks
。还有所有 the --strict
suite of compiler features, while you're at it. The --strict
option is a "standard" level of type which is used in a lot of code bases; if you have a question about TS and --strict
or one of its sub-features is not enabled, you will find fewer resources to help you. And the --strict
suite is composed of features which have, in real world code bases, solved more problems than they've caused. Features which tend to make things worse for the average code base are kept out, like --noUncheckedIndexedAccess
and --exactOptionalPropertyTypes
)。
以下代码在启用 strictNullChecks
时有效。
interface IData {
a: number;
b: string;
}
const data: Partial<IData> = {};
// I am doing "as const" to make 'a' and 'b' string literal
// keys of IData. In the real code, these keys would come from elsewhere.
for (const key of ['a', 'b'] as const) {
data[key] = undefined;
}
console.log(data);
flag关闭时报错:
Type 'any' is not assignable to type 'never'.(2322)
为什么?
有没有办法在不启用 strictNullChecks
或使用 any
的情况下克服这个问题?
也许你想要
interface IData {
a: number;
b: string;
}
const data: Partial<IData> = {};
for (const key of ['a', 'b']) {
data[key] = null;
}
console.log(data);
但根据 Calz 的评论,不太清楚您的用例是什么
当 the --strictNullChecks
compiler option is off, but I have not found an existing issue in GitHub about it. It is almost universally recommended 开启 --strictNullChecks
时,这似乎是 TypeScript 的限制,因此 [=120] 中的覆盖率几乎没有=] 以及有关关闭时的行为方式的文档。
我这里的分析是有几个东西交互不佳:
当
--strictNullChecks
关闭时,null
和undefined
被认为可分配给 几乎 任何类型。这几乎使他们bottom types like thenever
type。但是,无论出于何种原因,它们 不能 分配给never
类型。这是一个关键的区别(我可能认为这是一个错误或限制)。只有never
可分配给never
:declare let never: never; declare let any: any; declare let v: never; v = undefined; // error! v = null; // error v = any; // error v = never; // okay
当
--strictNullChecks
关闭时,null
和undefined
被吸收到unions(如never
):type Foo = string | undefined; // type Foo = string
当您尝试为联合类型的
key
赋值给obj[key]
时,TypeScript 要求该值可赋给 intersection of the value types for each key in the union, as implemented in microsoft/TypeScript#30769:interface Bar { x: number | string; y: string | boolean; } const bar: Bar = { x: 3, y: true }; for (const key of ['x', 'y'] as const) { bar[key] = 1; // error! number is not assignable to string bar[key] = "okay"; // okay }
综合起来:
在此代码中:
for (const key of ['a', 'b'] as const) {
data[key] = undefined;
}
因为 data
是 Partial<IData>
类型,--strictNullChecks
在 上,这个交集将是 (number | undefined) & (string | undefined)
,计算结果为只是 undefined
。因此,当 key
仅已知为 "a"
或 [=39 时,undefined
是您可以分配给 data[key]
的唯一安全值=].上面的赋值编译没有错误。
但是如果 --strictNullChecks
关闭 ,(number | undefined) & (string | undefined)
会崩溃为 number & string
,也就是 never
。并且 undefined
无论出于何种原因,都不能分配给 never
。上面的作业给了你你所面临的错误。
废话。
那么,您可以如何进行?假设您不想打开 --strictNullChecks
(这也是几乎普遍推荐的),并且您不想提交 issue in GitHub about it (which would probably end up being marked as "Working as Intended" or "Design Limitation", but maybe possibly would be marked as "Bug" which would be low on anyone's priority list to fix), then you can work around it via type assertion。您可以只说“undefined
可分配给 never
此处”,编译器将接受它:
for (const key of ['a', 'b'] as const) {
data[key] = undefined as never; // okay
}
这种类型安全吗?好吧,当 --strictNullChecks
关闭时,它的类型安全性并不比 undefined
的任何其他处理低。类型断言本质上让你做不安全的事情,所以你 从编译器那里承担一些安全责任。但不幸的是,你在这里能做的也好不了多少。
(好吧,你知道的,除了打开 --strictNullChecks
。还有所有 the --strict
suite of compiler features, while you're at it. The --strict
option is a "standard" level of type which is used in a lot of code bases; if you have a question about TS and --strict
or one of its sub-features is not enabled, you will find fewer resources to help you. And the --strict
suite is composed of features which have, in real world code bases, solved more problems than they've caused. Features which tend to make things worse for the average code base are kept out, like --noUncheckedIndexedAccess
and --exactOptionalPropertyTypes
)。