如何在打字稿中键入定义zip函数

时间:2020-05-31 12:47:43

标签: javascript typescript

说我想创建一个import 'dart:async'; import 'package:flutter/material.dart'; class OtpTimer extends StatefulWidget { @override _OtpTimerState createState() => _OtpTimerState(); } class _OtpTimerState extends State<OtpTimer> { final interval = const Duration(seconds: 1); final int timerMaxSeconds = 60; int currentSeconds = 0; String get timerText => '${((timerMaxSeconds - currentSeconds) ~/ 60).toString().padLeft(2, '0')}: ${((timerMaxSeconds - currentSeconds) % 60).toString().padLeft(2, '0')}'; startTimeout([int milliseconds]) { var duration = interval; Timer.periodic(duration, (timer) { setState(() { print(timer.tick); currentSeconds = timer.tick; if (timer.tick >= timerMaxSeconds) timer.cancel(); }); }); } @override void initState() { startTimeout(); super.initState(); } @override Widget build(BuildContext context) { return Row( mainAxisSize: MainAxisSize.min, children: <Widget>[ Icon(Icons.timer), SizedBox( width: 5, ), Text(timerText) ], ); } } 函数:

zip

当所有数组都拥有相同类型的元素时,为了进行类型定义,请定义此函数:

function zip(arrays){
    // assume more than 1 array is given and all arrays 
    // share the same length
    const len = arrays[0].length;
    const toReturn = new Array(len);
    for (let i = 0; i < len; i++){
        toReturn[i] = arrays.map(array=>array[i]);
    }
    return toReturn;
}

console.log(zip([
    [1,2,3],
    [4,5,6],
    [7,8,9],
    [10,11,12],
]));
/*
Output:
(3) [Array(4), Array(4), Array(4)]
0: (4) [1, 4, 7, 10]
1: (4) [2, 5, 8, 11]
2: (4) [3, 6, 9, 12]
*/

但是,当数组具有不同类型的元素时,我对于如何使用泛型类型完成类型定义感到困惑。

    function zip<T>(arrays: T[][]): T[][]{/* codes omited here */}

我想要的是

    const zipedResult = zip([[1,2,3],[true,false,true],['a','b','c']]);
    // error raises: Type 'false' is not assignable to type 'number'.(2322)

可以自动推断为 [[1,2,3],[true,false,true],['a','b','c']] ,而无需编写(number|boolean|string)[][] 甚至 推断为as (number|boolean|string)[][],结果[number[],boolean[],string[]]推断为zip

我应该如何正确键入定义[number, boolean, string][]来实现这些功能?

3 个答案:

答案 0 :(得分:0)

我能看到的唯一方法是为您要处理的每个数组大小定义一个不同的zip函数(因为我们需要能够准确地说出什么位于压缩结果的每个部分):

const zip3 = <T, U, V>(arrays: [T[], U[], V[]]): [T, U, V][] => {
    const len = arrays[0].length;
    const toReturn: [T, U, V][] = new Array(len);
    for (let i = 0; i < len; i++){
        toReturn[i] = [arrays[0][i], arrays[1][i], arrays[2][i]];
    }
    return toReturn;
};

const result = zip3([
    [1,2,3],
    [true, false, true],
    [7,8,9],
]);

console.log(result);

希望有人可以进来并展示出一种更好的方法来执行此操作,而不必根据要压缩的数组数来重新定义函数;

答案 1 :(得分:0)

最常见的解决方案是:

declare type UnionTypes = number[] | string[] | boolean[];
function zip(arrays: UnionTypes[]): UnionTypes[]

答案 2 :(得分:0)

我相信这是您发现TS并发症没有用的少数情况之一。我只能考虑将类型放宽到any并在必要时进行手动类型检查。

function zip(arrays: any[][]): any[][]{
    // assume more than 1 array is given and all arrays 
    // share the same length
    const len = arrays[0].length;
    const toReturn = new Array(len);
    for (let i = 0; i < len; i++){
        toReturn[i] = arrays.map(array => array[i]);
    }
    return toReturn;
}

const zipedResult = zip([[1,2,3],[true,false,true],['a','b','c']]);
console.log(zipedResult); // [[1, true, "a"], [2, false, "b"], [3, true, "c" ]]