我在TypeScript中编写extend
函数,可以:
即
extend({a: 1}, {b: 2}) → {a: 1, b: 2}
extend([1], [2]) → [1, 2]
此函数应该采用两个数组或两个对象,而不是每个对象中的一个。
我正在尝试为它提出正确的类型签名。理想情况下它会是这样的:
function extend<A, B, StrOrNum extends (string|number)>(
a: {[key: StrOrNum]: A},
b: {[key: StrOrNum]: B}): {[key: StrOrNum]: A&B} {
..
}
然而, tsc
抱怨索引签名必须是string
或number
:
[ts] An index signature parameter type must be 'string' or 'number'.
(parameter) key: StrOrNum extends string | number
如果我正在编写一个类型定义文件,我只需定义该函数的两个重载。我在实施时可以做类似的事情吗?或者这个函数是不连贯的 - 这是类型系统告诉我应该将它分成extendObject
和extendArray
函数的方式吗?
答案 0 :(得分:0)
您可以使用选项界面执行类似的操作:
interface ObjectOptions<T> { a: {[key: string]: T}, b: {[key: string]: T} }
interface ArrayOptions<T> { a: Array<T>; b: Array<T>; }
function extend<T>(params: ObjectOptions<T>|ArrayOptions<T>) { }
extend({a:[1],b:{k:1}}); // error
在某些情况下,您还可以使用定义重载的接口Foo
来扩展名为Foo
的类,但这很少是个好主意。所有这些都比仅具有两个不同的函数更麻烦,例如concat
用于数组,而merge
用于对象。
或者这个功能是不连贯的 - 这是类型系统告诉我的方式......
是。基于对象的映射是对象的映射,但是数组也是对象的映射。您的函数应该始终如一地处理这两个映射 - 您对数组的操作不应该产生:
extend([1], [2]) → [1, 2]
但是:
extend([1], [2]) → [2]
extend([1, 2], [7, undefined, 8]) → [7, 2, 8]
对于新的TypeScript代码,如果您遇到重载问题,请选择创建两种不同的方法,而不是尝试将类型检查破解为单个方法。 (最大的好处是无忧重构)