【发布时间】:2021-05-08 23:17:33
【问题描述】:
我正在努力根据输入参数推断类型。基本上我想使用对象的结构来推断返回类型(尽管不仅仅是 . 我认为诀窍是使用 conditional type 但我无法让它工作:
type Active = { name: string; active: true };
type Inactive = { name: string; active: false };
type IdWithAct = Active | Inactive;
export const getIdWithType = <
Arg extends IdWithAct,
T extends Arg extends Active ? 'ActiveItem' : 'InactiveItem'
>({
name,
active,
}: IdWithAct): {name: string, typeName: T } => ({
name,
typeName: active ? 'ActiveItem' : 'InactiveItem',
});
见playground。我查看了infer 解决方案,但这些示例对于我想要完成的(至少我认为)来说太微不足道了......
编辑
添加了来自 cmets 的示例。
重载
正如 cmets 所建议的,有重载选项,不幸的是,TypeScript 似乎在调用另一个函数时遇到了问题:
type ActivityWithName<T> = { name: string, active: T}
type IdWithAct = ActivityWithName<true> | ActivityWithName<false>;
type Types = 'ActiveItem' | 'InactiveItem'
type Ret<T> = { name: string, typeName: Types }
function getFragNameAndIdFromActive(args: ActivityWithName<true>): Ret<'ActiveItem'>
function getFragNameAndIdFromActive(args: ActivityWithName<false>): Ret<'InactiveItem'>
function getFragNameAndIdFromActive<Arg extends IdWithAct>({
name,
active,
}: IdWithAct): Ret<Types> {
return {
name,
typeName: active ? 'ActiveItem' : 'InactiveItem',
}
}
const retActive = getFragNameAndIdFromActive({ name: 'activeItem', active: true })
const retInactive = getFragNameAndIdFromActive({ name: 'activeItem', active: false })
function test(active: boolean) {
// active complaints: Type 'boolean' is not assignable to type 'false'.
const ret = getFragNameAndIdFromActive({ name: 'activeItem', active })
}
见playground。该解决方案很有吸引力,因为它对重载的意图相当明确。
运行时断言
运行时断言的建议有效,但在我看来它有点太神奇了,如果返回对象的差异不止一个值,它很可能会变得相当混乱:
type IdWithAct<T> = { name: string; active: T };
type Status<T> = T extends true ? 'ActiveItem' : 'InactiveItem'
export const getIdWithType = <T extends boolean>({
name,
active,
}: IdWithAct<T>) => ({
name,
typeName: (active ? 'ActiveItem' : 'InactiveItem') as Status<T>,
});
const foo = getIdWithType({ name: 'x', active: true }) // { name: string; typeName: "ActiveItem"; }
const bar = getIdWithType({ name: 'x', active: false }) // { name: string; typeName: "InactiveItem"; }
const test = (active: boolean) => getIdWithType({ name: 'x', active })
【问题讨论】:
-
只能使用类型断言,因为泛型只能在调用函数时解析,而不是在函数内部typescriptlang.org/play?#code/…
-
尝试编写重载
-
@captain-yossarian - 重载看起来很吸引人,但我无法让它们正常工作,请参阅我对问题的更新。
-
您可能会遇到这个问题 - stackoverflow.com/questions/56505560/…
-
W.R>T 上面的评论你可以检查这个 - typescriptlang.org/play?#code/…
标签: typescript typescript-generics