如何定义不包含特定成员的对象类型

时间:2019-09-06 04:50:02

标签: typescript

我正在处理我放入数据库/动作中和从中取出的对象,有时希望添加和删除特定于数据库/动作的字段。

例如,我有:

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>

Playground here

1 个答案:

答案 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>

根据目的,您可以执行以下操作:

  1. 更改回调类型以匹配stripFields Playground的类型:
type Callback<EntryLine> = (a: Omit<EntryEvent<EntryLine>, "type">) => void;
  1. thingThatTakesAndEvent Playground中进行投射:
function thingThatTakesAnEvent<EntryLine>(
  a: EntryEvent<EntryLine>,
  callback: Callback<EntryLine>
) {
  callback((stripFields(a, ["type"]) as unknown) as EntryLine);
}