如何在没有中间变量的情况下在typescript中重新分配类型别名?

zte4gxcn  于 2023-05-08  发布在  TypeScript
关注(0)|答案(1)|浏览(124)

考虑以下人为的示例:

type Response = {
  data: {
    bar: number;
  }
}

type MyData = {
  bar: number;
}

const responses: Response[] = [/**/];
const data = responses
  .map(response => response.data);

现在,如果您将鼠标悬停在IDE中的data上,它会告诉您它的类型是{ bar: number }[],而将鼠标悬停在.map函数上会给出一个更复杂(无法读取)的类型。在实际情况中,对于更复杂的类型,悬停信息变得完全无用,涉及这些类型的错误消息也是如此。
所以我想要的是一种方法来告诉TS我们想把它当作MyData类型。我想达到以下效果:

const data = responses
  .map(response => {
    const data: MyData = response.data; // errors if response.data doesn't satisfy MyData
    return data; // we're mapping to `MyData`, and not to `{bar : number}`
  });

我不想使用不必要的中间变量。理想情况下,我会使用这样的东西:

const data = responses
  .map(response => response.data with type MyData);

我有几个部分解决方案,但没有一个在现实世界的场景中工作得很好:

1:在Response类型中使用MyData

type Response = { data : MyData }

这要求我们可以更改输入类型,但这并不总是一个选项。例如,我们的响应类型可能是自动生成的,或者来自库。

2:显式输入data变量:

const data: MyData[] = responses.map(response => response.data);

虽然这使得data的类型更有用,但它仍然保留了.map的原始复杂类型。在不太人为的例子中,我们可能会链接几个操作(map/filter等),所有这些操作仍然使用无别名的类型签名。

3:使用as强制转换

const data = responses.map(response => response.data as MyData);

这不安全如果response.data更改为MyData | undefined,那么上面的代码编译得很好,即使它被破坏了。

4:使用satisfies强制转换

const data = responses.map(response => response.data satisfies MyData);

这是安全的,但不工作。它保留了原始类型(通过设计)。

5:显式设置类型参数

const data = responses.map<MyData>(response => response.data);

这对于我们的人造示例来说相当有效,但在现实世界的场景中,它并不总是有效。除了风格方面的考虑,主要问题是如果我们的操作需要多个类型参数,我们现在需要提供ALL参数。这是不可取的,有时甚至不可行。
因此,我正在寻找一种方法来“重新分配”值的类型,而不使用中间变量。有这种事吗?我如何才能做到这一点?

nx7onnlm

nx7onnlm1#

您可以按如下方式注解arrow function的返回类型:

const arrowFn = (x: string): number => x.length
// annotation -----------> ^^^^^^^^

所以你可以这样调用responses.map()

const data = responses.map((response): MyData => response.data);

其中response参数的类型仍然是上下文类型,因此您不必注解它。
请注意,注解位于参数列表的右括号“)”和箭头“=>”之间。如果你的函数只有一个参数,你仍然需要把它括在括号里才能编译。也就是说,你不能这样做:

const data = responses.map(response: MyData => response.data); // error

即使无注解的返回类型版本在没有括号的情况下也能正常工作:

const data = responses.map(response => response.data); // okay

遗憾的是,我找不到我认为的这个特性的“官方文档”。TypeScript Handbook描述了函数语句的返回类型注解,而(已存档且大部分已过时)language specification并没有像我希望的那样清楚地说明这一点,尽管它有一个关于箭头函数的部分。如果有人找到了这方面的权威文档(不包括编译器本身或一些使用但没有提到该功能的文档),我很乐意将其链接到这里。
Playground链接到代码

相关问题