如何从官方的Typescript文档中获取条件类型在这个示例中工作?

hgb9j2n6  于 2023-04-07  发布在  TypeScript
关注(0)|答案(2)|浏览(102)

我正在看typescript文档,并在条件类型上登陆了this page
我尝试以这种方式实现createLabel函数:

interface IdLabel {
  id: number /* some fields */;
}
interface NameLabel {
  name: string /* other fields */;
}
type NameOrId<T extends number | string> = T extends number
  ? IdLabel
  : NameLabel;

function createLabel<T extends number | string>(nameOrId: T): NameOrId<T>  {
  const label: NameOrId<T> = (typeof nameOrId === 'number') ? { id: nameOrId }: { name: nameOrId} ;
  return label;
}

我在创建label时遇到一个错误

Type '{ id: number; } | { name: string; }' is not assignable to type 'NameOrId<T>'.
  Type '{ id: number; }' is not assignable to type 'NameOrId<T>'.

我做错了什么?

7kjnsjlb

7kjnsjlb1#

代码的问题是TypeScript无法从createLabel函数中推断出返回值的正确类型。要解决这个问题,可以使用类型Assert来显式告诉TypeScript返回值的类型应该是什么。
下面是正确的代码:

interface IdLabel {
  id: number /* some fields */;
}

interface NameLabel {
  name: string /* other fields */;
}

type NameOrId<T extends number | string> = T extends number
  ? IdLabel
  : NameLabel;

function createLabel<T extends number | string>(nameOrId: T): NameOrId<T> {
  return typeof nameOrId === "number"
    ? { id: nameOrId } as NameOrId<T>
    : { name: nameOrId } as NameOrId<T>;
}

const Name = createLabel("5"); // Type is NameLabel
const Id = createLabel(5); // Type is IdLabel

Playground

c90pui9n

c90pui9n2#

我相信你的问题与this one密切相关
Titian的回答解释了所有的细节,所以为了完整起见,我只提供一个适用于你的例子的Playground链接。我使用了一个单独的实现签名,只使用联合类型,但这不是唯一的方法。

相关问题