【发布时间】:2021-08-16 23:10:57
【问题描述】:
我有一个用例构建到目标“状态”:
type State = { foo: number, bar: number, baz?: string };
当我开始时,我很可能还没有达到完整的状态,但我很高兴能适应Partial<State> 的形状。我想做什么,当我达到传说中的State 状态时如何推断。
为了帮助我实现这个目标,我首先创建了一个名为 Resolve 的实用程序类型:
type Resolve<T extends Partial<State>> =
T extends infer U
? U extends State ? State : Partial<State>
: never;
当给定这样的推断类型时,此实用程序可以工作:
const implicit1 = { foo: 5 };
const implicit2 = { foo: 5, bar: 10 };
// YAY: resolves to Partial<State>
const implicitResolve1: Resolve<typeof implicit1> = implicit1;
// YAY: resolves to State
const implicitResolve2: Resolve<typeof implicit2> = implicit2;
然而,一旦一个类型被表达为Partial<State>,它就拒绝推断它可能是State类型:
const explicit1: Partial<State> = { foo: 5 };
const explicit2: Partial<State> = { foo: 5, bar: 10 };
// YAY: correctly resolves to Partial<State>
const explicitResolve1: Resolve<typeof explicit1> = explicit1;
// SAD FACE: also resolves to Partial<State> even though the intent
// was for it to be recognized that it is a valid State!
const explicitResolve2: Resolve<typeof explicit2> = explicit2;
在我更广泛的解决方案中,我已经有一个类型后卫在等待,我认为这会给我我需要的超能力:
type TypeGuard<T> = (thing: unknown) => thing is T;
const tg: TypeGuard<State> = (thing: unknown): thing is State => {
return typeof thing === "object"
&& typeof (thing as any)?.foo === "number"
&& typeof (thing as any)?.bar === "number";
};
function SuperResolve(thing: unknown, tg: TypeGuard<State>) {
return tg(thing) ? thing as State : thing as Partial<State>
}
// SHOCKED: this resolves to Partial<State> too!
const fnResolve = SuperResolve(explicit2, tg);
我现在的能力已经到了尽头......当然有一些方法可以检测Partial<T> 何时达到<T>。
【问题讨论】:
-
我脑子里唯一能想到的可能是Required<T>?
-
我不确定一旦你用类型明确地标记了它,你是否能够获得该值的“实际”类型。例如,您可以使用
const explicit3: Partial<State> = new Date as any。 -
@ErikPhilips 如果我在 Resolve 实用程序中将 Partial
强制转换为 Required >,则会失败。您打算如何使用它? -
@y2bd 并没有真正理解你的意思……
any的分配让这个例子变得毫无用处。目的是使用部分结构,并且随着时间的推移构建它,您会测试它是否达到“完成”状态。 -
@ken 我相信,一旦您告诉 TypeScript 一个值的显式类型(在您的情况下是通过键入变量),TS 就会“丢弃”它自己为该值推断的类型。这意味着您无法再获取值的推断类型并将其视为
Partial<State>之外的任何内容,类似于将某些内容转换为any时,您将无法再看到值的原始类型是什么(在我的情况下,日期)。
标签: typescript typescript-typings typescript-generics