Typescript Prisma 风格的条件返回类型不按预期工作。

huangapple go评论63阅读模式
英文:

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&lt;T extends ResolveQueryOptions&gt; = keyof {
  [K in keyof T as T[K] extends false ? never : K]: K;
};

type StringToType&lt;
  S extends ResolveQueryOptions,
  T extends SelectKeys&lt;S&gt;
&gt; = T extends &#39;group&#39; ? Group : T extends &#39;user&#39; ? User : never;

type QueryResult&lt;T extends ResolveQueryOptions&gt; = {
  result: {
    [K in SelectKeys&lt;T&gt;]: StringToType&lt;T, K&gt;[];
  };
};

function example&lt;T extends ResolveQueryOptions&gt;(options: T): QueryResult&lt;T&gt; {
  const a: any = {};

  if (options.group) {
    a.result.group = [] as Group[];
  }
  if (options.user) {
    a.result.user = [] as User[];
  }

  return a as QueryResult&lt;T&gt;;
}

const result = example(defaultResolveQueryOptions);

result.result.group;
result.result.user; // I expect this to be undefined and give a TS error, however it doesn&#39;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 (&lt;T extends ResolveQueryOptions&gt;), 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!

huangapple
  • 本文由 发表于 2023年5月13日 17:44:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/76242060.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定