0

Hey guys I was wondering if there was a correct way to do this. I am currently trying to define a type of variable based on conditional logic but am currently running into issues. Both Interface1 and Interface2 are defined as interfaces in Typescript. With the first console.log of the type of the eventProps variable I get an undefined which I thought I would originally log out the type of: 'Interface1 | Interface2'. And with the second console.log I log out is of type object which I thought would log out either 'Interface1' or 'Interface2'. Am I doing something wrong/is there a better way to do what I am trying to accomplish?

let eventProps: Interface1 | Interface2;
console.log(typeof eventProps);

switch (event) {
  case 'event1':
    eventProps = { isCorrect: true, name: 'Mike' } as Interface1;
  default:
    eventProps = { isCorrect: true } as Interface2;
}
console.log(typeof eventProps);
1
  • Look for "type guards" in typescript's documentation. Commented Nov 30, 2021 at 20:54

1 Answer 1

1

When you write Typescript code, it is compiled to Javascript and the type annotations and checking are wiped away.

typeof is a Javascript operator that only reports what primitive type the object is, so it's working as intended.

If you're using a named class or prototype, console.log will include the type name. And you can use instanceof to test it at runtime:

class ConcreteType1 implements Interface1 {
  isCorrect: boolean;
  name: string;

  constructor(isCorrect: boolean, name: string) {
    this.isCorrect = isCorrect;
    this.name = name;
  }
}

const x:ConcreteType1 = getAConcreteType1();
console.log(x) // includes 'ConcreteType1'
if (x instanceof ConcreteType1) {
  // typescript lets you use Interface1 fields in here
}

But the best, most idiomatic way to deal with type shapes and interfaces at runtime is to use discriminating unions.

Simply add a common field, in this example 'type', that is set to a string literal. Then if eventProps is a union type, eventProps.type is 'interface1' | 'interface2' which makes testing at runtime and narrowing the type easy.

interface Interface1 {
  type: 'interface1';
  /* some fields */
};

interface Interface2 {
  type: 'interface2';
  /* some fields */
}

const x: Interface1 | Interface2 = getOne();
console.log(x) // includes { type: 'interface1', ... } so you can tell
if (x.type === 'interface1') {
  // typescript lets you use Interface1 fields in here
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.