是否可以键入两个函数数组参数,以使第二个参数的长度比第一个参数长?

时间:2019-12-05 03:45:14

标签: typescript

函数数组参数是否使第二个参数的长度比第一个参数长?

const func = (arr1: number[], arr2: number[]) => {}

2 个答案:

答案 0 :(得分:0)

序言:我对TS的了解还不是很先进(但是),尽管这个问题还没有更好的答案,但我看到了最终的结果(随着真正的大师之一的加入,我会放弃,并提供更合适的解决方案)

type plusone<T> =
    T extends 1 ? 2 :
    T extends 2 ? 3 :
    T extends 3 ? 4 : never;

type plusoneLength<T> = { length: plusone<T> };

function f<T>(left: { length: T }, right: plusoneLength<T>): void { }

f([1, 2] as const, [1, 2, 3] as const);

ts游乐场:https://www.typescriptlang.org/play/?ssl=1&ssc=1&pln=11&pc=1#code/C4TwDgpgBGA2CuBnA9gOwgHgCoD4oF4AoKEqLKCAD2AlQBNEoBGKAfigCYoAuY08qjXqMu7AMw8+JAdVoMoE9gBYeUdADcIAJwDchQqEgwEKdABlaAc2AALbHnxQA3lFhXb3Y0jSZcUAL56hABm8KgAxsAAlmhQwfYAFG7BwJ4ubqjWNp7k-gA0UFpRljapXqYQFpm29gCUnurIUXTOAfrBCQDaTAUcALpQAIaM4WiIwAXdvQViA8NQo6jjtXpAA

答案 1 :(得分:0)

是的...一种。

declare function takesTupleAndTupleOneLonger<
    A extends unknown[] | readonly unknown[] & { length: Tail<B>['length']; },
    B extends (unknown[] | readonly unknown[])
>(a: A, b: B): void;

takesTupleAndTupleOneLonger(['baz'] as const, ['foo', 'bar'] as const); // OK
takesTupleAndTupleOneLonger([] as const, ['foo', 'bar'] as const, ); // Error
takesTupleAndTupleOneLonger(['baz', 42] as const, ['foo', 'bar'] as const); // Error

请注意此处使用的as const:这是因为如果没有这些AB都将被推断为类型string[]。换句话说,

takesTupleAndTupleOneLonger(['baz'], ['foo', 'bar']); // OK
takesTupleAndTupleOneLonger([], ['foo', 'bar']); // OK ← but shouldn’t be!
takesTupleAndTupleOnelonger(['baz', 42], ['foo', 'bar']); // OK ← but shouldn’t be!

此外,如果您根本没有硬编码的数组,而只想检查类似a.length === b.length - 1之类的内容,则无法“保存”结果到类型域中,这样它将成为takesTupleAndTupleOneLonger可用-您仍然会被允许,因为您将要处理(对于编译器而言)长度未知的数组,但这种方式并不安全。

不过,如果要处理编译时已知的数组,这可能会很有用。

最后,我的实现依赖于Tail,它是在环境.d.ts文件中定义的,如下所示:

/** Used internally for `Tail`. */
type AsFunctionWithArgsOf<T extends unknown[] | readonly unknown[]> = (...args: T) => any;

/** Used internally for `Tail` */
type TailArgs<T> = T extends (x: any, ...args: infer T) => any ? T : never;

/** Elements of an array after the first. */
type Tail<T extends unknown[] | readonly unknown[]> = TailArgs<AsFunctionWithArgsOf<T>>;