我在使用带有“嵌套”接口和ReadonlyArray
的泛型时遇到麻烦。如何在不丢失filterList
参数类型的情况下运行list
函数?
interface INumber {
value: number
}
interface IState {
readonly numbers: ReadonlyArray<INumber>
}
var state: IState = {
numbers: [{ value: 1 }, { value: 2 }, { value: 3 }, { value: 4 }]
}
function filterList<T>(list: T) {
return list.filter(x => x.value > 2);
}
// Error: Property 'filter' does not exist on type 'T'.
const res = filterList(state.numbers);
由于使用ReadonlyArray,将filterList
函数更改为以下内容将失败。
function filterList(list: INumber[]) {...}
// Error: Argument of type 'ReadonlyArray<INumber>' is not assignable
// to parameter of type 'INumber[]'. Property 'pop' is missing in
// type 'ReadonlyArray<INumber>'.
const res = filterList(state.numbers);
处理这种情况的最佳实践是什么? 谢谢!
答案 0 :(得分:1)
您有几种选择。 ReadonlyArray<T>
是Array
的子集,因此我们可以将T
包含为具有以下值的某物的ReadonlyArray
:
var state: IState = {
numbers: [{ value: 1 }, { value: 2 }, { value: 3 }, { value: 4 }]
}
function filterList<T extends ReadonlyArray<{value : number }>>(list: T){
return list.filter(x => x.value > 2);
}
const res = filterList(state.numbers); // ok
var arr = [{ value: 1 }, { value: 2 }, { value: 3 }, { value: 4 }]
const res2 = filterList(arr); //ok
尽管类型参数作为列表并没有太多好处,因为filter
将同时返回ReadonlyArray
和Array
的常规数组,因此可以像好吧:
function filterList<T extends {value : number }>(list: ReadonlyArray<T>){
return list.filter(x => x.value > 2);
}
const res = filterList(state.numbers); // ok
var arr = [{ value: 1 }, { value: 2 }, { value: 3 }, { value: 4 }]
const res2 = filterList(arr); //ok
如果您希望filterList
保留传入的是只读数组还是常规数组,则可以使用第一个版本并返回T
,但是您需要使用类型断言来进行filter
pe的结果键入为ReadonlyArray
function filterList<T extends ReadonlyArray<{value : number }>>(list: T): T{
return list.filter(x => x.value > 2) as any;
}
const res = filterList(state.numbers); // ok, res is ReadonlyArray<INumber>
var arr = [{ value: 1 }, { value: 2 }, { value: 3 }, { value: 4 }]
const res2 = filterList(arr); //ok, res s { value: number; }[]