对象保持可为空性的强制转换字段

Cast fields of object keeping nullability

提问人:Valentin Vignal 提问时间:8/28/2023 更新时间:8/28/2023 访问量:20

问:

我正在尝试创建一个类型,该类型将对象的所有属性强制转换为 。这是我现在所拥有的:DateToNumberDatenumber

type LiteralDateToNumber<T> = T extends Date
  ? number
  : T extends Date | null
  ? number | null
  : T extends Date | undefined
  ? number | undefined
  : T extends Date | null | undefined
  ? number | null | undefined
  : T;

/**
 * @description Converts all `Date` properties to `number`.
 */
type DateToNumber<T> = {
  [K in keyof T]: LiteralDateToNumber<T[K]>;
};

我想保留 ,这里所有带有 或 的检查。nullability| null| undefined

这大多有效,但是使用其他类型时会出现一个问题,而不是可以为空的类型:Date

type MyType = {
  aDate: Date;
  aString: string;
  bDate: Date | null;
  bString: string | null;
  cDate: Date | undefined;
  cString: string | undefined;
  dDate: Date | null | undefined;
  dString: string | null | undefined;
  eDate?: Date;
  eString?: string;
  fDate?: Date | null;
  fString?: string | null;
  gDate?: Date | undefined;
  gString?: string | undefined;
  hDate?: Date | null | undefined;
  string?: string | null | undefined;
};
type MyCastedType = DateToNumber<MyType>;

在这种情况下,等效于:MyCastedType

type MyCastedType = {
  aDate: number;
  aString: string;
  bDate: number | null;
  bString: string | number | null;
  cDate: number | undefined;
  cString: string | number | undefined;
  dDate: number | null | undefined;
  dString: string | number | null | undefined;
  eDate?: number | undefined;
  eString?: string | number | undefined;
  fDate?: number | null | undefined;
  fString?: string | number | null | undefined;
  gDate?: number | undefined;
  gString?: string | number | undefined;
  hDate?: number | null | undefined;
  hString?: string | number | null | undefined;
};

它有几个问题,我希望它等同于:

type MyCastedType = {
  aDate: number;
  aString: string;
  bDate: number | null;  // And not `bString: string | number | null;`
  bString: string | null;
  cDate: number | undefined;
  cString: string | undefined;  // And not `cString: string | number | undefined;`
  dDate: number | null | undefined;
  dString: string | null | undefined; // And not `dString: string | number | null | undefined;`
  eDate?: number; // And not `eDate?: number | undefined;`
  eString?: string; // And not `eString?: string | number | undefined;`
  fDate?: number | null;  // And not `fDate?: number | null;`
  fString?: string | null; // And not `fString?: string | number | null | undefined;`
  gDate?: number | undefined;
  gString?: string | undefined; // And not `gString?: string | number | undefined;`
  hDate?: number | null | undefined;
  string?: string | null | undefined; // And not `hString?: string | number | null | undefined;`
};

如何实现此类型?DateToNumber

TypeScript 类型 转换 TypeScript-Generics

评论


答:

1赞 shantr 8/28/2023 #1

应将 LiteralDateToNumber 简化为:

type LiteralDateToNumber<T> = T extends Date ? number : T;

当您为泛型提供类型联合时,它实际上会分发它

type A = LiteralDateToNumber<Date | null>;
// is equivalent to
type B = LiteralDateToNumber<Date> | LiteralDateToNumber<null>;

// => number | null

你的问题是,用作条件的联合也将被分配使用LiteralDateToNumber

type A<T> = T extends Date| null ? number : T;
// is equivalent to saying if T extends either Date or null (not exactly Date | null)
// => equivalent to
type B<T> = T extends Date ? number : T extends null ? number : T;

type Test = Test<null>;
// => null does extends Date | null
// => number;