【问题标题】:Using Tuples in TypeScript (Type Inference)在 TypeScript 中使用元组(类型推断)
【发布时间】:2020-09-24 03:55:03
【问题描述】:

鉴于这个稍微人为的例子:

['List', 'Of', 'Names']
        .map((name, index) => [name, index % 2])
        .map(([name, num]) => );

为什么string | number 类型的最后一行中的 name 和 num 显然被推断为字符串和数字的数组,你们是否知道是否有一种方法可以使用类型推断,以便 name 是一个字符串,而 num 是分别是一个数字?

【问题讨论】:

    标签: typescript


    【解决方案1】:

    对于数组字面量类型推断不推断元组,它推断数组,所以

    var foo = ["", 0]; // foo is Array<string | number> not [string, number]
    

    我还没有找到这方面的文档,但是 pull request 添加对元组的支持在声明它们时从不使用推理,我猜这是故意的。

    在您的情况下,您可以指定类型参数:

    ['List', 'Of', 'Names']
            .map<[string, number]>((name, index) => [name, index % 2])
            .map(([name, num]) => name + "");
    

    2.9及以下解决方案

    如果这对您来说是一个常见问题,或者创建一个元组辅助函数:

    function tuple<T1, T2, T3, T4, T5>(data: [T1, T2, T3, T4, T5]) : typeof data
    function tuple<T1, T2, T3, T4>(data: [T1, T2, T3, T4]) : typeof data
    function tuple<T1, T2, T3>(data: [T1, T2, T3]) : typeof data
    function tuple<T1, T2>(data: [T1, T2]) : typeof data
    function tuple(data: Array<any>){
        return data;
    }
    
    ['List', 'Of', 'Names']
            .map((name, index) => tuple([name, index % 2]))
            .map(([name, num]) => name + "");
    

    3.0解决方案

    自从我发布原始答案以来,打字稿已经改进了它的推断,能够推断出剩余参数的元组类型。有关详细信息,请参阅PR。有了这个特性,我们可以编写一个更短的tuple 函数:

    function tuple<T extends any[]> (...data: T){
        return data;
    }
    
    ['List', 'Of', 'Names']
            .map((name, index) => tuple(name, index % 2))
            .map(([name, num]) => name + "");
    

    【讨论】:

    • 显式输入是我想要避免的。我也可以使用对象并使用对象解构.map(({name, num}) =&gt; ...),但也不是很简洁。感谢元组函数的想法!
    【解决方案2】:

    您可以使用const assertion

    ['List', 'Of', 'Names']
        .map((name, index) => [name, index % 2] as const) // insert `as const` here
        .map(([name, num]) => { }); // name: string, num: number
    

    看看playground sample

    【讨论】:

    • 非常优雅!当您想在 React 中扩展 useState 结果但保持类似的类型时,这尤其有用,例如,在更改状态的函数中添加副作用。结果变成了readonly
    • 这应该是答案,因为这是解决此问题的当前方法,尽管先前的答案确实有历史信息。
    • 这个解决方案的一个缺点是它会产生一个只读元组。如果这不是问题 - 效果很好!
    猜你喜欢
    • 1970-01-01
    • 2021-04-15
    • 2020-04-21
    • 2012-11-26
    • 2018-07-03
    • 1970-01-01
    • 2019-09-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多