Wilhelm Olejnik
Wilhelm Olejnik

Reputation: 2507

Require at least one property of given type

consider the following code

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);

is it possible to define such type X that the following will happen:

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

In other words is it possible to require at least one property but it may have any name ?

demo: https://stackblitz.com/edit/typescript-fekr1o

Upvotes: 1

Views: 74

Answers (1)

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

Reputation: 249466

Not sure we can do better than a custom error. We can force a type error on the parameter using a conditional type if the union of values in the type (T[keyof T]) does not contain 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

Upvotes: 1

Related Questions