如何正确返回带有对象的元组

时间:2019-11-12 21:21:26

标签: typescript tuples

下面,我有一个函数,该函数返回带有2个对象的元组。

const example = () => {
    return [{meow: true}, { woof: false}]
}

const [catStuff, dogStuff] = example()

catStuff.meow // why is this possibly undefined? why does this possibly contain `woof`?

我很好奇为什么会有工会?我如何获得该元组以返回两个不同的对象?

catStuff: {
    meow: boolean,
    woof?: undefined
} | {
    woof: boolean,
    meow?: undefined
}

3 个答案:

答案 0 :(得分:1)

您可以使用以下

function tuple<T extends any[]>(...args: T): T {
  return args;
}

const example = () => {
  return tuple({meow: true}, { woof: false})
}

编译器正确推断:

const example: () => [{
    meow: boolean;
}, {
    woof: boolean;
}]

我从Tuples in rest parameters and spread expressions #24897获得了tuple功能

对于只读元组,可以使用:

const example = () => {
  return [{meow: true}, { woof: false}] as const;
}

在这里,编译器推断

const example: () => readonly [{
    readonly meow: true;
}, {
    readonly woof: false;
}]

答案 1 :(得分:0)

您问为什么。这取决于您要如何处理结果。就Typescript而言,您的元组可以解释为

  

[typescript]元素隐式具有“ any”类型,因为类型为“ {   喵woof ?:未定义; } | {woof:boolean;喵?:   未定义}'。

例如,以下和类似用法应该可以正常工作:

const example = () => {
    return [{meow: true}, { woof: false}]
}

const [catStuff, dogStuff] = example()

console.log(`${catStuff.meow}`)
console.log(`${dogStuff.woof}`)

以下内容无效

console.log(`${dogStuff.meow}`)
console.log(`${catStuff.woof}`)

之所以编译catStuff.woof是因为Typescript仅检查元组中是否存在woof;它不会检查与之关联的元素。但是在运行时,由于未为woof定义catStuff,因此您会得到一个undefined

以下内容将不会编译,因为元组/对象类型中不存在speak

console.log(`${catStuff.speak}`)

答案 2 :(得分:0)

这与example是一个函数无关;如果直接将返回值定义为常量,则会得到相同的推论:

const c = [{ meow: true }, { woof: false }];
// c: ({ meow: boolean, woof?: undefined } | { woof: boolean, meow?: undefined })[]

根本原因是Typescript推断文字数组具有数组类型,即使它可以推断更具体的元组类型也是如此。这是2017年在Typescript问题跟踪器上的raised as an issue,但该问题已关闭且未采取任何措施。这可能是因为as one commenter noted

  

推断元组类型确实是不安全的。在其他问题上对此有很多讨论。当某人正在使用他们不打算成为元组的数组时,它将并且可能破坏很多其他代码。 ...仅仅因为数组文字是const并且是异构的,并不意味着它打算成为一个元组。特别是因为即使使用元组类型,所有运行时数组功能都可用。

也就是说,即使将c声明为对数组的const引用,c的内容仍可以由其他代码更改,例如c.pop(),因此通常假设c始终按此顺序始终具有这两种不同类型的两个元素,这通常是不安全的。


如果您希望函数example具有不同的返回类型,只需添加一个显式类型注释:

type MeowWoof = [{ meow: boolean }, { woof: boolean }];

const example: () => MeowWoof = () => {
    return [{ meow: true }, { woof: false }]
};

还请注意,c的最具体可能的类型是[{ meow: true }, { woof: false }],而不是[{ meow: boolean }, { woof: boolean }]