Typescript安全地实现类型相关的功能

时间:2019-07-19 14:24:45

标签: typescript

我正在尝试安全地实现以下功能

type OneOrAll<T extends any[]> =
    T extends { length: 1 } ? T[0] :
    T

interface Foo {
  // ...
}

declare function oneOrAll<A extends Foo[]>(...as: A): OneOrAll<A>;

应根据给定参数的长度返回FooFoo[]。例如

const x: Foo = oneOrAll(fooA);
const xs: Foo[] = oneOrAll(fooA, fooB);

类型已经可以解决了,但是我正在努力编写实现。我的第一次尝试是

function oneOrAll<A extends Foo[]>(...as: A): OneOrAll<A> {
    if (as.length == 1) {
        return as[0]; // Type 'Foo' is not assignable to type 'OneOrAll<A>'.
    }
    return as; // Type 'A' is not assignable to type 'OneOrAll<A>'.
               //   Type 'Foo[]' is not assignable to type 'OneOrAll<A>'.
}

但是,这不能与内联错误一起编译。实现此功能的正确方法是什么?

1 个答案:

答案 0 :(得分:1)

您可以使用函数重写来实现您的功能:

function oneOrAll<A extends [Foo]>(x: A[0]): A[0]
function oneOrAll<A extends Foo[]>(...xs: A): A
function oneOrAll<A extends Foo[]>(...xs: A): A[0] | A {
    if (xs.length === 1) {
        return xs[0]
    }
    return xs
}

您得到以下结果:

declare const foo: Foo
const x = oneOrAll(foo) // Foo
const y = oneOrAll(foo, foo) // [Foo, Foo]