'InputType[]' 类型的参数不可分配给 'GenericType[]' 类型的参数打字稿
Argument of type 'InputType[]' is not assignable to parameter of type 'GenericType[]' Typescript
我的目的是编写一个辅助函数,其目的是根据作为第二个参数传递的 key
按字母顺序对对象数组(第一个参数)进行动态排序。
函数:
interface GenericObject {
[key: string]: string;
}
export const sortAlphabetically = (array: Array<GenericObject>, sortBy: keyof GenericObject) => {
let isKeyValid = false;
// check the key exists in the object before attempting to sort by it
if (array.length > 0) {
isKeyValid = array.every(obj => Object.prototype.hasOwnProperty.call(obj, sortBy) && typeof obj[sortBy] === 'string');
}
if (isKeyValid) {
array.sort((a: GenericObject, b: GenericObject) =>
a[sortBy].toLowerCase() < b[sortBy].toLowerCase()
? -1
: a[sortBy].toLowerCase() > b[sortBy].toLowerCase()
? 1
: 0,
);
return array;
} else {
return;
}
};
所以现在,即使在能够测试我的功能之前,如果我尝试这样做:
export interface Person {
name: string;
surname: string;
}
const people: Person[] = [
{name: 'John', surname: 'Smith'},
{name: 'Tony', surname: 'Denver'},
{name: 'Mary', surname: 'Howard'},
]
sortAlphabetically(people, 'name');
或者这个:
export interface Car {
model: string;
make: string;
}
const cars: Car[] = [
{model: 'Golf', make: 'Volkswagen'},
{model: 'X1', make: 'BMW'},
{model: 'Clio', make: 'Renault'},
]
sortAlphabetically(cars, 'make');
我收到错误:
TS2345: Argument of type 'Person[]' is not assignable to parameter of type 'GenericObject[]'. Type 'Person' is not assignable to type 'GenericObject'. Index signature is missing in type 'Person'.
Car[]
.
也是如此
作为一个辅助函数,关键是它需要适应any
类型的对象,将在数组内部传递,而不抱怨类型。
因此,我很确定问题出在我定义 GenericObject
.
的方式上
有人可以指出我在这里遗漏了什么吗?非常感谢。
首先,您不能将 Person
转换为 GenericObject
,因为 Person
在 GenericObject
只允许 string
个值。
其次,关于您遇到的错误有一个未解决的问题
https://github.com/microsoft/TypeScript/issues/15300
您应该将 interface
替换为 type
type GenericObject = {
[key: string]: string | number;
}
export const sortAlphabetically = (array: Array<GenericObject>, sortBy: keyof GenericObject) => {
// Whatever
};
export type Person = {
name: string;
id: number;
};
const people: Person[] = [
{name: 'John', id: 1},
{name: 'Tony', id: 2},
{name: 'Mary', id: 3},
]
sortAlphabetically(people, 'name');
嗯,首先要说的是正确实现会很麻烦
你要找的是:
- 传递数组
- 传递属于字符串的键属性
- 按该键对数组进行排序。
对于上面的那些你需要做一些事情:
- 缩小关键参数以仅允许字符串属性
GenericObject
类型不足以单独提供
- 您需要一些仅过滤字符串属性的 type-mapper
- 由于
GenericObject
和 Person
类型之间没有关系,因此您不能进行此转换:array.sort((a: GenericObject, b: GenericObject)
- 如果将该数组类型概括为
any
左右类型,那么这将不起作用:a[sortBy].toLowerCase()
因为 .toLowerCase()
必须适用于任何类型的对象 属性.
所以你需要一个类型保护来将 属性 缩小为 GenericObject
所以 TL;DR
interface GenericObject {
[key: string]: string;
}
type FilterFlags<Base, Condition> = {
[Key in keyof Base]:
Base[Key] extends Condition ? Key : never
};
type AllowedNames<Base, Condition> =
FilterFlags<Base, Condition>[keyof Base];
type SubType<Base, Condition> =
Pick<Base, AllowedNames<Base, Condition>>;
export function sort<T>(array: Array<T>, sortBy: keyof SubType<T, string>) {
let isKeyValid = false;
// check the key exists in the object before attempting to sort by it
if (array.length > 0) {
isKeyValid = array.every(obj => Object.prototype.hasOwnProperty.call(obj, sortBy));
}
if (isKeyValid) {
array.sort((a, b) =>
(isGeneric(a, sortBy) && isGeneric(b, sortBy)) ? // narrow down type to GenericObject so that .toLowerCase becomes valid here
a[sortBy].toLowerCase() < b[sortBy].toLowerCase()
? -1
: a[sortBy].toLowerCase() > b[sortBy].toLowerCase()
? 1
: 0 :
1 // this shouldn't be happening
);
return array;
} else {
return;
}
};
const isGeneric = (a: any, key: keyof typeof a): a is GenericObject =>
typeof a[key] === "string";
export interface Person {
id: number;
name: string;
}
const people: Person[] = [
{ name: 'John', id: 1 },
{ name: 'Tony', id: 2 },
{ name: 'Mary', id: 3 },
]
sort(people, "name"); // this won't allow passing "id" as parameter
SubType
类型映射器取自 here
我的目的是编写一个辅助函数,其目的是根据作为第二个参数传递的 key
按字母顺序对对象数组(第一个参数)进行动态排序。
函数:
interface GenericObject {
[key: string]: string;
}
export const sortAlphabetically = (array: Array<GenericObject>, sortBy: keyof GenericObject) => {
let isKeyValid = false;
// check the key exists in the object before attempting to sort by it
if (array.length > 0) {
isKeyValid = array.every(obj => Object.prototype.hasOwnProperty.call(obj, sortBy) && typeof obj[sortBy] === 'string');
}
if (isKeyValid) {
array.sort((a: GenericObject, b: GenericObject) =>
a[sortBy].toLowerCase() < b[sortBy].toLowerCase()
? -1
: a[sortBy].toLowerCase() > b[sortBy].toLowerCase()
? 1
: 0,
);
return array;
} else {
return;
}
};
所以现在,即使在能够测试我的功能之前,如果我尝试这样做:
export interface Person {
name: string;
surname: string;
}
const people: Person[] = [
{name: 'John', surname: 'Smith'},
{name: 'Tony', surname: 'Denver'},
{name: 'Mary', surname: 'Howard'},
]
sortAlphabetically(people, 'name');
或者这个:
export interface Car {
model: string;
make: string;
}
const cars: Car[] = [
{model: 'Golf', make: 'Volkswagen'},
{model: 'X1', make: 'BMW'},
{model: 'Clio', make: 'Renault'},
]
sortAlphabetically(cars, 'make');
我收到错误:
TS2345: Argument of type 'Person[]' is not assignable to parameter of type 'GenericObject[]'. Type 'Person' is not assignable to type 'GenericObject'. Index signature is missing in type 'Person'.
Car[]
.
作为一个辅助函数,关键是它需要适应any
类型的对象,将在数组内部传递,而不抱怨类型。
因此,我很确定问题出在我定义 GenericObject
.
有人可以指出我在这里遗漏了什么吗?非常感谢。
首先,您不能将 Person
转换为 GenericObject
,因为 Person
在 GenericObject
只允许 string
个值。
其次,关于您遇到的错误有一个未解决的问题
https://github.com/microsoft/TypeScript/issues/15300
您应该将 interface
替换为 type
type GenericObject = {
[key: string]: string | number;
}
export const sortAlphabetically = (array: Array<GenericObject>, sortBy: keyof GenericObject) => {
// Whatever
};
export type Person = {
name: string;
id: number;
};
const people: Person[] = [
{name: 'John', id: 1},
{name: 'Tony', id: 2},
{name: 'Mary', id: 3},
]
sortAlphabetically(people, 'name');
嗯,首先要说的是正确实现会很麻烦
你要找的是:
- 传递数组
- 传递属于字符串的键属性
- 按该键对数组进行排序。
对于上面的那些你需要做一些事情:
- 缩小关键参数以仅允许字符串属性
GenericObject
类型不足以单独提供- 您需要一些仅过滤字符串属性的 type-mapper
- 由于
GenericObject
和Person
类型之间没有关系,因此您不能进行此转换:array.sort((a: GenericObject, b: GenericObject)
- 如果将该数组类型概括为
any
左右类型,那么这将不起作用:a[sortBy].toLowerCase()
因为.toLowerCase()
必须适用于任何类型的对象 属性. 所以你需要一个类型保护来将 属性 缩小为GenericObject
所以 TL;DR
interface GenericObject {
[key: string]: string;
}
type FilterFlags<Base, Condition> = {
[Key in keyof Base]:
Base[Key] extends Condition ? Key : never
};
type AllowedNames<Base, Condition> =
FilterFlags<Base, Condition>[keyof Base];
type SubType<Base, Condition> =
Pick<Base, AllowedNames<Base, Condition>>;
export function sort<T>(array: Array<T>, sortBy: keyof SubType<T, string>) {
let isKeyValid = false;
// check the key exists in the object before attempting to sort by it
if (array.length > 0) {
isKeyValid = array.every(obj => Object.prototype.hasOwnProperty.call(obj, sortBy));
}
if (isKeyValid) {
array.sort((a, b) =>
(isGeneric(a, sortBy) && isGeneric(b, sortBy)) ? // narrow down type to GenericObject so that .toLowerCase becomes valid here
a[sortBy].toLowerCase() < b[sortBy].toLowerCase()
? -1
: a[sortBy].toLowerCase() > b[sortBy].toLowerCase()
? 1
: 0 :
1 // this shouldn't be happening
);
return array;
} else {
return;
}
};
const isGeneric = (a: any, key: keyof typeof a): a is GenericObject =>
typeof a[key] === "string";
export interface Person {
id: number;
name: string;
}
const people: Person[] = [
{ name: 'John', id: 1 },
{ name: 'Tony', id: 2 },
{ name: 'Mary', id: 3 },
]
sort(people, "name"); // this won't allow passing "id" as parameter
SubType
类型映射器取自 here