![](/img/trans.png)
[英]How to define an object of specific functions as a type or an interface?
[英]How to define an object type that does _not_ include a specific member
我正在处理我放入和退出数据库/动作的对象,有时希望添加和删除特定于数据库/动作的字段。
例如,我有:
type EntryEvent<EntryLine> = { type: 'entry' } & EntryLine;
在其他地方,我希望删除type
成员,以便将EntryEvent<EntryLine>
回EntryLine
。 为此,我使用以下实用程序函数:
export function stripFields<T extends object, K extends keyof T>(
o: T,
fields: K[]
): Omit<T, K> {
const result: Partial<T> = { ...(<object>o) };
for (const field of fields) {
delete result[field];
}
return <Omit<T, K>>result;
}
麻烦的是,生成的对象将不会被识别为EntryLine
。
如果我尝试将以下内容分配给EntryLine
类型:
stripFields(event, ['type'])
我会得到:
Argument of type 'Pick<EntryEvent<EntryLine>, Exclude<keyof EntryLine, "type">>' is not assignable to parameter of type 'EntryLine'.
'Pick<EntryEvent<EntryLine>, Exclude<keyof EntryLine, "type">>' is assignable to the constraint of type 'EntryLine', but 'EntryLine' could be instantiated with a different subtype of constraint 'Pick<object, never>' ts(2345)
据我所知,这是有道理的,因为如果通用类型EntryLine
包含type
成员,则stripFields
的结果将不再是EntryLine
(因为它将丢失其type
成员)。
有什么方法可以定义约束通用类型EntryLine
以便它不允许带有type
字段的对象? 还是有其他解决方法?
更新:
以下代码为我重现了该问题:
type EntryEvent<EntryLine> = { type: "entry" } & EntryLine;
type MyEntryLine = {
a: Date;
};
export function stripFields<T extends object, K extends keyof T>(
o: T,
fields: K[]
): Omit<T, K> {
const result: Partial<T> = { ...(<object>o) };
for (const field of fields) {
delete result[field];
}
return <Omit<T, K>>result;
}
type Callback<EntryLine> = (a: EntryLine) => void;
function thingThatTakesAnEvent<EntryLine>(a: EntryEvent<EntryLine>, callback: Callback<EntryLine>) {
callback(stripFields(a, ["type"]));
}
function thingThatTakesAMyEntryLine(a: MyEntryLine) {
console.log(a.a);
}
declare let event: EntryEvent<MyEntryLine>;
thingThatTakesAnEvent(event, thingThatTakesAMyEntryLine);
“ Pick <EntryEvent <EntryLine>,Exclude <EntryLine的键,“类型” >>”可分配给类型“ EntryLine”的约束,但是可以使用约束“ {}”的另一个子类型实例化“ EntryLine”。
这种形式的错误消息基本上意味着,您试图从传入的泛型类型参数中推断出太多信息,而泛型类型参数只有调用者/客户端才能知道。 Typescript不再认为您对它的类型的猜测是安全的。
关于您的代码,可以将其翻译为:
function thingThatTakesAnEvent<EntryLine>(
a: EntryEvent<EntryLine>,
callback: Callback<EntryLine>
) {
callback(stripFields(a, ["type"]));
//------ error ------//
}
==> stripFields
的返回类型为Pick< EntryEvent< EntryLine>, Exclude< keyof EntryLine, "type">>
,可以分配给约束EntryLine
(默认为{}
),但是如果调用者调用了该方法像这样的函数: thingThatTakesAnEvent<{foo: "bar"}>
? 在函数内部,我们不知道它是{foo: "bar"}
,我们应该使用EntryLine
调用callback
,但是我们使用了特定的子类型,这可能与调用者不EntryLine
。
根据目的,您可以执行以下操作:
stripFields
Playground的类型: type Callback<EntryLine> = (a: Omit<EntryEvent<EntryLine>, "type">) => void;
thingThatTakesAndEvent
Playground中进行转换 : function thingThatTakesAnEvent<EntryLine>(
a: EntryEvent<EntryLine>,
callback: Callback<EntryLine>
) {
callback((stripFields(a, ["type"]) as unknown) as EntryLine);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.