`Required` 不会从 class 通用属性中删除 `undefined`(错误?)?
`Required` does not remove `undefined` from class generic properties (bug?)?
我偶然发现了标准 utility type Required
的以下情况:
type A = {x?: number;}
type B1 = Required<A>['x']; // number, OK
type B2<T extends A> = Required<T>['x']; // number, OK
class C1 {
public f(x: Required<A>['x']) { // x is number, OK
const y = x + 1; // OK
}
}
class C2<T extends A> {
public f(x: Required<T>['x']) { // x is number | undefined, NOT OK
const y = x + 1; // ERROR
}
}
我无法想象这是预期的行为。为什么 C2
-case 与 C1
-case 不同?起初我认为它可能与一般泛型有关,但自从 B2
案例起作用以来,似乎只有 class 泛型受到影响。
我可以做任何事情 - 除了明确地说出类似 x: Exclude<Required<T>['x'], undefined>
的东西 - 使 x
(以及 A
的其他潜在属性)真的 必需(即不是未定义的)?
所以,答案是 T
不等于 A
。这意味着 T
可以是另一种类型,它可以做一些事情并实现 A
中的键
如果你想让它们相等,你需要这样做。
class C2<T extends Required<A>> {
public f(x: Required<T>["x"]) {
// x is number, OK
const y = x + 1; // OK
}
}
Here, we’ll create an interface that has a single .length property and then we’ll use this interface and the extends keyword to denote our constraint:
更新:
Required
来自 {x?: number} -> {x: number}
.
但是如果调用
Required<{x: number | undefined}>
x
仍未定义。
当您将 T
传递给泛型时,field?: someType
将转换为 field: someType | undefined
。
在你的情况下,你应该摆脱 undefined 两次,?
和 undefined
类型也是如此。
type FullRequired<T extends object> = Required<{
[K in keyof T]: Exclude<T[K], undefined>;
}>;
class C2<T extends A> {
public f(x: FullRequired<T>["x"]) {
// x is number OK
const y = x + 1; // OK
}
}
我偶然发现了标准 utility type Required
的以下情况:
type A = {x?: number;}
type B1 = Required<A>['x']; // number, OK
type B2<T extends A> = Required<T>['x']; // number, OK
class C1 {
public f(x: Required<A>['x']) { // x is number, OK
const y = x + 1; // OK
}
}
class C2<T extends A> {
public f(x: Required<T>['x']) { // x is number | undefined, NOT OK
const y = x + 1; // ERROR
}
}
我无法想象这是预期的行为。为什么 C2
-case 与 C1
-case 不同?起初我认为它可能与一般泛型有关,但自从 B2
案例起作用以来,似乎只有 class 泛型受到影响。
我可以做任何事情 - 除了明确地说出类似 x: Exclude<Required<T>['x'], undefined>
的东西 - 使 x
(以及 A
的其他潜在属性)真的 必需(即不是未定义的)?
所以,答案是 T
不等于 A
。这意味着 T
可以是另一种类型,它可以做一些事情并实现 A
中的键
如果你想让它们相等,你需要这样做。
class C2<T extends Required<A>> {
public f(x: Required<T>["x"]) {
// x is number, OK
const y = x + 1; // OK
}
}
Here, we’ll create an interface that has a single .length property and then we’ll use this interface and the extends keyword to denote our constraint:
更新:
Required
来自 {x?: number} -> {x: number}
.
但是如果调用
Required<{x: number | undefined}>
x
仍未定义。
当您将 T
传递给泛型时,field?: someType
将转换为 field: someType | undefined
。
在你的情况下,你应该摆脱 undefined 两次,?
和 undefined
类型也是如此。
type FullRequired<T extends object> = Required<{
[K in keyof T]: Exclude<T[K], undefined>;
}>;
class C2<T extends A> {
public f(x: FullRequired<T>["x"]) {
// x is number OK
const y = x + 1; // OK
}
}