簡體   English   中英

Typescript - 具有聯合類型的交集運算符

[英]Typescript - intersection operator with union type

這是一個事件發射器的設計:

type EventMap = Record<string, any>;

type EventKey<T extends EventMap> = string & keyof T;
type EventReceiver<T> = (params: T) => void;

interface Emitter<T extends EventMap> {
  on<K extends EventKey<T>>
    (eventKey: K, fn: EventReceiver<T[K]>): void;
  emit<K extends EventKey<T>>
    (eventKey: K, params: T[K]): void;
}

// example usage
const emitter = eventEmitter<{
  data: Buffer | string;
  end: undefined;
}>();

// OK!
emitter.on('data', (x: string) => {});

// Error! 'string' is not assignable to 'number'
emitter.on('data', (x: number) => {});

設計有效,但有兩件事我不明白:

  1. EventKey :為什么要在此處添加string &

  2. 為什么我們需要 generics Konemit方法, eventKey參數的類型不能簡單地是keyof T嗎?

提前謝謝了。

EventKey:為什么要在此處添加字符串&?

交集string &...用於確保只有實際上是string類型的鍵才能用於定義EventKey類型。

即使EventMap被定義為Record<string,any>您仍然可以為其分配具有非字符串屬性的 object:

const a: EventMap = {
  foo: 'bar',
  100: 'baz', // whoops, number property
}

為什么? 因為對象可以有多余的屬性

因此,在這種情況下, string & keyof T將導致never用於非string類型的流氓屬性。

eventKey 參數的類型不能簡單地是 keyof T 嗎?

這是為了允許將鍵定義為聯合類型,它們會擴展string (另請參閱此答案):

type EnumK = 'alpha' | 'beta'
type MyObject = {[P in EnumK]: string }

const obj: SomeObj = {
  alpha: 'foo',
  beta: 'bar'
}

這里obj的鍵的類型是string擴展,即字符串文字類型alphabeta之間的並集。 因此,通過使用K extends...您可以捕獲這種關系並確保類型索引T[K]中的類型安全。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM