如果参数是数组,则返回值数组,否则返回值

Luk*_*kas 7 typescript typescript-typings

我想允许一个string或一个 s 数组string作为参数。根据是否传递了一个string或一个数组,我想返回一个值或一个值数组。string

function(input: string | string[]): inputIsArray ? returnValue[] : returnValue {}
Run Code Online (Sandbox Code Playgroud)

我怎样才能为此编写正确的类型?

T.J*_*der 5

我想我会使用重载(但可以使用条件类型,见下文)。在此示例中,我使用了numberforreturnType但当然这只是为了示例:

function example(input: string): number;
function example(input: string[]): number[];
function example(input: string | string[]): number | number[] {
    if (Array.isArray(input)) {
        return (<string[]>input).map(str => Number(str));
    }
    return Number(<string>input);
}

const result1 = example("42");         // `result1`'s type is `number`
const result2 = example(["42", "67"]); // `result2`'s type is `number[]`
Run Code Online (Sandbox Code Playgroud)

操场上

请注意,其中第三个只是实现签名。唯一有效的呼叫签名example是前两个。


关于您的评论,询问条件类型是否可以实现这一点,我在场外联系了Titian Cernicova-Dragomir,他是 SO 的 TypeScript 专家之一。他说他已经看到了这个问题,正要发布重载答案时,他看到我有:-),并且他也会为此使用重载 - 但如果你想这样做,则可以使用条件类型方式,这样做会打开第三个调用签名。这是他的想法:

function example<T extends string | string[]>(input: T): T extends string ? number : number[];
function example(input: string | string[]): number | number[] {
    if (Array.isArray(input)) {
        return (<string[]>input).map(str => Number(str));
    }
    return Number(<string>input);
}

const result1 = example("42");         // `result1`'s type is `number`
const result2 = example(["42", "67"]); // `result2`'s type is `number[]`
Run Code Online (Sandbox Code Playgroud)

操场上

请注意引入如何T让我们在参数类型和返回值的(条件)类型中使用它。(这是我在尝试将条件类型应用于此时错过的关键部分。)

他指出,条件类型版本开辟了第三种调用方式:使用类型为 的参数string | string[],而不是其中之一:

declare const value: string | string[];
let result3 = example(value) // `result3`'s type is `number | number[]`. Would not have worked with overloads.
Run Code Online (Sandbox Code Playgroud)

操场上

因此,如果您想要第三个调用签名,可以使用条件类型来获取它。否则,重载仅提供前两个签名。