Typescript 可选 属性 类型泛型
Typescript optional property type generic
我希望我的函数接受任何类型的对象,但如果对象有 属性 'id',请确保它是字符串或数字。
这是最简单的例子:
interface FnItem {
id?: string | number;
};
function fn<T extends FnItem>(item: T, callback: (item: T) => void) {
console.log(item.id);
callback(item)
};
fn({ name: 'Michel' }, item => item.name);
fn({ name: 'Michel', id: 12 }, item => item.name);
它抛出这个错误
Argument of type '{ name: string; }' is not assignable to parameter of type 'FnItem'.
Object literal may only specify known properties, and 'name' does not exist in type 'FnItem'
---
Property 'name' does not exist on type 'FnItem
错误告诉你所有你需要的。 name
在您的 FnItem
类型中不存在。如果您想添加任意键,可以通过添加 属性 或添加索引签名来修复它,如下所示:
interface FnItem {
id?: string | number;
[key: string]: any; // or whatever types you accept
};
至于泛型,我暂时不知道你需要它做什么,因为你可以简单地将函数定义为
function fn(item: FnItem): void
如果你想传递一个泛型,那么你需要告诉函数什么具体类型实现了你的接口:
interface FnItem {
id?: string | number;
};
function fn<T extends FnItem>(item: T, callback: (item: T) => void) {
console.log(item.id);
callback(item);
};
fn<myType>({ name: 'Michel', id: 12 }, (item:myType) => { console.log(item.name); });
fn<myType>({ name: 'Michel' }, (item:myType) => { console.log(item.name); });
class myType implements FnItem
{
name: string = "";
id?: number;
}
假设 FnItem
可能是具有任何属性的任何对象或 id
是 number|string
的任何对象我宁愿坚持这个解决方案:
type FnItem = Record<string, unknown>
type IdValidation<Obj extends Record<string, unknown>> =
Obj extends { id: infer Id } ? Id extends string | number ? Obj : Obj & { id: never } : Obj;
function fn<T extends FnItem,>(item: IdValidation<T>, callback: (item: IdValidation<T>) => void) {
console.log(item.id);
callback(item)
};
fn({ name: 'Michel' }, item => item.name);
fn({ name: 'Michel', id: 12 }, item => item.id);
fn({ name: 'Michel' }, item => item.ya); // error
fn({ name: 'Michel', id: [] }, item => item.id); // id is highlighted as a wrong property
由于第一个参数可能是任何对象,我们应该允许传递 Record<string,unknown>
,这反过来会禁用我们关于 id
是 number|string
的约束。这就是我添加 IdValidation
实用程序类型的原因。它只是检查 id
属性 是否满足条件。如果满足 - 保持 id
不变,否则 - 将 id
类型替换为 never
。使用 never
可让您仅突出显示不正确的 属性,这使其易于阅读和理解。
我希望我的函数接受任何类型的对象,但如果对象有 属性 'id',请确保它是字符串或数字。
这是最简单的例子:
interface FnItem {
id?: string | number;
};
function fn<T extends FnItem>(item: T, callback: (item: T) => void) {
console.log(item.id);
callback(item)
};
fn({ name: 'Michel' }, item => item.name);
fn({ name: 'Michel', id: 12 }, item => item.name);
它抛出这个错误
Argument of type '{ name: string; }' is not assignable to parameter of type 'FnItem'.
Object literal may only specify known properties, and 'name' does not exist in type 'FnItem'
---
Property 'name' does not exist on type 'FnItem
错误告诉你所有你需要的。 name
在您的 FnItem
类型中不存在。如果您想添加任意键,可以通过添加 属性 或添加索引签名来修复它,如下所示:
interface FnItem {
id?: string | number;
[key: string]: any; // or whatever types you accept
};
至于泛型,我暂时不知道你需要它做什么,因为你可以简单地将函数定义为
function fn(item: FnItem): void
如果你想传递一个泛型,那么你需要告诉函数什么具体类型实现了你的接口:
interface FnItem {
id?: string | number;
};
function fn<T extends FnItem>(item: T, callback: (item: T) => void) {
console.log(item.id);
callback(item);
};
fn<myType>({ name: 'Michel', id: 12 }, (item:myType) => { console.log(item.name); });
fn<myType>({ name: 'Michel' }, (item:myType) => { console.log(item.name); });
class myType implements FnItem
{
name: string = "";
id?: number;
}
假设 FnItem
可能是具有任何属性的任何对象或 id
是 number|string
的任何对象我宁愿坚持这个解决方案:
type FnItem = Record<string, unknown>
type IdValidation<Obj extends Record<string, unknown>> =
Obj extends { id: infer Id } ? Id extends string | number ? Obj : Obj & { id: never } : Obj;
function fn<T extends FnItem,>(item: IdValidation<T>, callback: (item: IdValidation<T>) => void) {
console.log(item.id);
callback(item)
};
fn({ name: 'Michel' }, item => item.name);
fn({ name: 'Michel', id: 12 }, item => item.id);
fn({ name: 'Michel' }, item => item.ya); // error
fn({ name: 'Michel', id: [] }, item => item.id); // id is highlighted as a wrong property
由于第一个参数可能是任何对象,我们应该允许传递 Record<string,unknown>
,这反过来会禁用我们关于 id
是 number|string
的约束。这就是我添加 IdValidation
实用程序类型的原因。它只是检查 id
属性 是否满足条件。如果满足 - 保持 id
不变,否则 - 将 id
类型替换为 never
。使用 never
可让您仅突出显示不正确的 属性,这使其易于阅读和理解。