需要至少一个给定类型的属性

时间:2019-07-31 19:10:18

标签: typescript

考虑以下代码

class FootballService {
  getMatches() { return [] }
}

function defineMatchesOnComponent(component: X) {
  component.matches = Object.values(component)
    .find(property => property instanceof FootballService)
    .getMatches();
}

class ComponentA {
  constructor(public footballService: FootballService, public otherProp: string) {}
}

class ComponentB {
  constructor(public whateverNameYouWant: FootballService, public otherProp: number) {}
}

class ComponentC {
  constructor(public otherProp: string) {}
}

const a = new ComponentA(new FootballService(), 'xd');
const b = new ComponentB(new FootballService(), 2);
const c = new ComponentC(true);

是否可以定义将发生以下情况的类型X

defineMatchesOnComponent(a); // should be ok
defineMatchesOnComponent(b); // should be ok
defineMatchesOnComponent(c); // should be type error

换句话说,是否可以要求至少一个属性,但是它可以有任何名称?

演示:https://stackblitz.com/edit/typescript-fekr1o

1 个答案:

答案 0 :(得分:1)

不确定我们可以做得比自定义错误更好。如果类型(T[keyof T])中的值的并集不包含FootballService

,我们可以使用条件类型对参数强加类型错误
class FootballService {
  getMatches() { return [] }
}

function defineMatchesOnComponent<T>(component: T & (FootballService extends T[keyof T] ? {} : "No FootballService property was defined")) {
   /* */
}

class ComponentA {
  constructor(public footballService: FootballService, public otherProp: string) {}
}

class ComponentB {
  constructor(public whateverNameYouWant: FootballService, public otherProp: number) {}
}

class ComponentC {
  constructor(public otherProp: boolean) {}
}

const a = new ComponentA(new FootballService(), 'xd');
const b = new ComponentB(new FootballService(), 2);
const c = new ComponentC(true);


defineMatchesOnComponent(a); // should be ok
defineMatchesOnComponent(b); // should be ok
defineMatchesOnComponent(c); // should be type error