英文:
Typescript Prisma style conditional return type not working as expected
问题
我正在尝试创建一种自定义条件类型,类似于Prisma的类型,根据输入参数的属性返回不同的类型给函数。
我的简化代码如下:
type 组 = {};
type 用户 = {};
type 解析查询选项 = {
用户: boolean;
组: boolean;
};
const 默认解析查询选项: 解析查询选项 = {
组: true,
用户: false,
};
type 选择键<T extends 解析查询选项> = keyof {
[K in keyof T as T[K] extends false ? never : K]: K;
};
type 字符串转类型<
S extends 解析查询选项,
T extends 选择键<S>
> = T extends '组' ? 组 : T extends '用户' ? 用户 : never;
type 查询结果<T extends 解析查询选项> = {
结果: {
[K in 选择键<T>]: 字符串转类型<T, K>[];
};
};
function 例子<T extends 解析查询选项>(选项: T): 查询结果<T> {
const a: any = {};
if (选项.组) {
a.结果.组 = [] as 组[];
}
if (选项.用户) {
a.结果.用户 = [] as 用户[];
}
return a as 查询结果<T>;
}
const 结果 = 例子(默认解析查询选项);
结果.结果.组;
结果.结果.用户; // 我期望这是undefined并且给出TS错误,然而它并没有
英文:
I am trying to create a custom conditional type much like Prisma's types which return a different type based on the properties inside the input parameter to a function.
My simplified code looks like this:
type Group = {};
type User = {};
type ResolveQueryOptions = {
user: boolean;
group: boolean;
};
const defaultResolveQueryOptions: ResolveQueryOptions = {
group: true,
user: false,
};
type SelectKeys<T extends ResolveQueryOptions> = keyof {
[K in keyof T as T[K] extends false ? never : K]: K;
};
type StringToType<
S extends ResolveQueryOptions,
T extends SelectKeys<S>
> = T extends 'group' ? Group : T extends 'user' ? User : never;
type QueryResult<T extends ResolveQueryOptions> = {
result: {
[K in SelectKeys<T>]: StringToType<T, K>[];
};
};
function example<T extends ResolveQueryOptions>(options: T): QueryResult<T> {
const a: any = {};
if (options.group) {
a.result.group = [] as Group[];
}
if (options.user) {
a.result.user = [] as User[];
}
return a as QueryResult<T>;
}
const result = example(defaultResolveQueryOptions);
result.result.group;
result.result.user; // I expect this to be undefined and give a TS error, however it doesn't
According to some articles (this and this) that I found related to this topic it should work like this:
By extending the type in the function (<T extends ResolveQueryOptions>
), but not specifying it when calling the function (const result = example(defaultResolveQueryOptions);
) Typescript should resolve the type from the input parameter (options T
).
Any help is much appreciated!
答案1
得分: 0
I have found the answer and would like to add it here if anyone else runs into this issue at some point.
The problem was that my defaultResolveQueryOptions
had a type specified (: ResolveQueryOptions
) and Typescript then chooses to use this type, instead of inferring the type based on the value.
Changing that declaration from:
const defaultResolveQueryOptions: ResolveQueryOptions = {
group: true,
user: false,
};
To
const defaultResolveQueryOptions = {
group: true,
user: false,
} as const;
Fixes the problem!
英文:
So I have found the answer and would like to add it here if anyone else runs into this issue at some point.
The problem was that my defaultResolveQueryOptions
had a type specified (: ResolveQueryOptions
) and Typescript then chooses to use this type, instead of inferring the type based on the value.
Changing that declaration from:
const defaultResolveQueryOptions: ResolveQueryOptions = {
group: true,
user: false,
};
To
const defaultResolveQueryOptions = {
group: true,
user: false,
} as const;
Fixes the problem!
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论