typescript 键入除最后一个元素之外的相同类型元素的数组

z0qdvdin  于 2023-02-25  发布在  TypeScript
关注(0)|答案(1)|浏览(116)

我有一个服务器响应,它是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
92dk7w1h

92dk7w1h1#

这是一个不幸的服务器响应。给你两个答案:
1.一个假设你不能改变这种React的答案。
1.建议更改响应的答案。:-)

如果你不能改变答案

如果您被这个响应卡住了,那么不幸的是,在从它中取出部分时,您也会被类型Assert卡住(the PR中介绍了TypeScript对元组开头或中间的rest元素的处理-感谢jcalz指出这一点)。
您具有响应类型的权限:

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

既然我们在做类型Assert,至少让我们把它们 Package 在一个可重用的、可测试的函数中,这个函数产生一个更容易使用的结构:

// 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示例

如果你能改变它

    • 如果您可以更改服务器响应,使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链接

相关问题