matteok
matteok

Reputation: 2199

determine type of parameter that could have multiple types in typescript

Given a function with a parameter of different types, how do I find out which type was passed to the function?

Example

interface SomeCustomInterface {
    title: string
}

interface OtherCustomInterface {
    subtitle: string
}


interface A {
    value: string
}

interface B {
    value: number
}

interface C {
    value: SomeCustomInterface
}

interface D {
    value: OtherCustomInterface
}

function doSomething(parameter: A | B | C | D): string {
    switch(parameter.type) { 
        // I know the cases are not valid TS. What should I do instead?
        case A:
            return parameter.value
        case B:
            return parameter.value.toString()
        case C:
            return parameter.value.title
        case D:
            return parameter.value.subtitle
    }
}

I know that there are type guards but I have concerns with those

  1. They need to be able to uniquely identify each type. I see that some people add a property kind or type which allows them to identify a type in order to type guard it. This seems like a lot of overhead and boilerplate to me though.

  2. You need to write a custom function for each type like type is A or type is B which again would lead to massive overhead in my context.

What is the appropriate way to approach this in typescript?

Upvotes: 3

Views: 9063

Answers (1)

user13258211
user13258211

Reputation:

Basically there are only 2 options as described in the accepted answer of this question.

What you can do is check that the shape of an object is what you expect, and TypeScript can assert the type at compile time using a user-defined type guard that returns true (annotated return type is a "type predicate" of the form arg is T) if the shape matches your expectation:

For class types you can use JavaScript's instanceof to determine the class an instance comes from, and TypeScript will narrow the type in the type-checker automatically.

A side note from myself:

If you have the same propertyname you can potentially refactor your code using generics, like:

interface A {
    value: string
}

interface B {
    value: number
}

interface C {
    value: SomeCustomInterface
}

interface D {
    value: OtherCustomInterface
}

can be

interface GenericInterface<T>{
 value: T
}

Upvotes: 3

Related Questions