`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:

Generics docs

更新:

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
  }
}