【问题标题】:Typing an array of elements of the same type, except the last one输入相同类型的元素数组,除了最后一个
【发布时间】:2023-02-22 01:12:23
【问题描述】:

我有一个服务器响应,它是 IFoo 元素的数组,但最后一个是 IBar 类型。

我想删除最后一个元素并将其分配给一个新变量。我该怎么做?

我尝试将响应键入为元组,但 TypeScript 不会像我预期的那样拆分元素的类型。

const response = [...IFoo[], IBar];
const lastElement = response.pop()

// typeof response returns [...IFoo[], IBar]
// typeof lastElement returns IFoo | IBar | undefined

//expected result:
// typeof response returns IFoo[]
// typeof lastElement returns IBar

【问题讨论】:

  • 谈到服务器响应,TypeScript 使用静态数据(已知数据)。我不认为 TypeScript 可以从运行时可用的数据动态推断类型。您能分享一下您是如何确定返回 [...IFoo[], IBar] 的响应类型的吗?因为我假设 TypeScript 不会知道这些信息,除非你“以某种方式”告诉它会发生什么
  • 我不认为你可以改变服务器响应?这将是很多如果它返回 [IBar, ...IFoo[]] 会更好。或者你被你得到的东西困住了?

标签: typescript tuples typescript-typings


【解决方案1】:

这是一个不幸的服务器响应。假设您坚持使用它,那么可悲的是,我认为您在从中拆解零件时也坚持使用类型断言。(如果可以更改,请参见水平线下方。)您有正确的响应类型:

type ResponseTuple = [...IFoo[], IBar];

由于您可能坚持使用类型断言,让我们至少将它们包装在一个可重用、可测试的函数中,该函数生成一个更易于使用的结构:

// A function to split the response into something easier to work with
function splitResponse(response: ResponseTuple): {bar: IBar, foos: IFoo[]} {
    if (response.length < 1) {
        // No bar at all => error (you could make another decision, but this is an example)
        throw new Error(`Can't split an empty response`);
    }
    // Grab the bar non-destructively, using a type assertion :-(
    const bar = response[response.length - 1] as IBar;
    // Grab the foos non-destructively, using a type assertion :-(
    const foos = response.slice(0, -1) as IFoo[];
    // Return the more useful format
    return {bar, foos};
}

使用它:

const { bar, foos } = splitResponse(someResponse);

Playground example


如果您可以更改服务器响应,这样IBar就在前面,事情是很多更简单:

// The type of the response
type ResponseTuple = [IBar, ...IFoo[]];

// Dividing it up
const [ bar, ...foos] = someResponse;
console.log(bar);
//          ^? const bar: IBar
console.log(foos);
//          ^? const foos: IFoo[]

Playground link

【讨论】:

  • 遗憾的是服务器返回 [...IFoo[], IBar] 而不是 [IBar, ...IFoo[]]... 否则我们可以做 const [bar, foos] = response;
  • @vera - 确实如此(但使用...const [bar, ...foos] = response;)。我本来打算对此表示同情,并询问他们是否可以更改它,但我似乎忘记了。 :-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-10-19
  • 2012-01-05
  • 1970-01-01
  • 1970-01-01
  • 2016-02-09
  • 2012-02-18
  • 2020-12-11
相关资源
最近更新 更多