typescript 数组类型的类型保护

dz6r00yl  于 2023-10-22  发布在  TypeScript
关注(0)|答案(4)|浏览(130)

对非数组类型使用typeof类型保护非常简单(来自docs的示例):

function padLeft(value: string, padding: string | number) {
    if (typeof padding === "number") {
        return Array(padding + 1).join(" ") + value;
    }
    if (typeof padding === "string") {
        return padding + value;
    }
    throw new Error(`Expected string or number, got '${padding}'.`);
}

然而,当涉及到数组类型时,它变得更加复杂。我假设下面的代码可以工作:

function join(array: number[] | string[]): string {
    if (typeof array[0] === 'number') {
        return foo(array);
    } else {
        return bar(array)
    }
}

function foo(n: number[]): string {
    return n.join();
}

function bar(s: string[]): string {
    return s.join();
}

对我来说很简单:预期类型是数字数组或字符串数组。
如果数组中第一个元素的类型是number,那么数组的类型是number[]。否则,这是一个字符串数组。
不幸的是,TypeScript编译器并不那么聪明,我得到了一个编译错误:
“number[]”类型的参数|“string[]"不能分配给”string[]“类型的参数
我该怎么做?

pieyvz9o

pieyvz9o1#

答案是用户定义的类型保护
你可以定义一个类型保护,它将决定数组是否是数字数组:

function isNumbers(array: number[] | string[]): array is number[] {
    return typeof array[0] === 'number'
}

阅读更多关于用户定义的类型保护here
下面是你的代码的一个工作示例:

function join(array: number[] | string[]): string {
    if (isNumbers(array)) {
        return foo(array);
    } else {
        return bar(array)
    }
}

function foo(n: number[]): string {
    return n.join();
}

function bar(s: string[]): string {
    return s.join();
}

function isNumbers(array: number[] | string[]): array is number[] {
    return typeof array[0] === 'number'
}

TypeScript playground示例。

2uluyalo

2uluyalo2#

JeB's answer对我来说是一个很好的开始,但我需要更健壮的东西,因为我必须处理任意输入。我的想法是

function isNumberArray(value : unknown) : value is number[] {
    if (!Array.isArray(value)) {
        return false;
    }

    if (value.some((v) => typeof v !== "number")) {
        return false;
    }

    return true;
}
velaa5lx

velaa5lx3#

下面是一个字符串数组的例子。我想你可以让它通用并测试任何类型:

export const isStringArray = (value: unknown) => {
  return Array.isArray(value) && value.every((val) => typeof val === "string");
};
daupos2t

daupos2t4#

关于类型 predicate 中Typescript的用户定义类型保护的最新文档可以在这里找到。
作为对所选答案的补充,根据typescript文档,您可以在为自定义类型定义typeguards时使用类型Assert:

function isFish(pet: Fish | Bird): pet is Fish {
  return (pet as Fish).swim !== undefined;
}

相关问题