我正在处理我放入数据库/动作中和从中取出的对象,有时希望添加和删除特定于数据库/动作的字段。
例如,我有:
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);
字段的对象?还是有其他解决方法?
更新:
以下代码为我重现了问题:
<agm-map [latitude]="latitide" [longitude]="langtitude" [zoom]="zoom">
<agm-marker [latitude]="lat1" [longitude]="lng1"></agm-marker>
<agm-marker [latitude]="lat2" [longitude]="lng2"></agm-marker>
</agm-map>
答案 0 :(得分:0)
'Pick
,Exclude >'可分配给类型'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"}
,应该用callback
来调用EntryLine
,但是我们使用了特定的子类型,它可能不是调用者的正确子类型。 / p>
根据目的,您可以执行以下操作:
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);
}