Home > other >  Does Generic Object match a certain Type?
Does Generic Object match a certain Type?

Time:09-29

Is there a way to determine whether a generic Object matches a certain Type? I have an ngOnChanges method where I'd like to perform different actions based on the type of the generic returned.

Here's a simplified example of what I'm trying to do. Here's the response object:

myResponseData = {
    name: 'fu'
    address: '123 ABC Lane'
}

Can I determine if this matches either one of these objects?

const personModel = {
    name: string;
    address: string;
}

const placeModel = {
    city: string;
    country: string;
}

I've tried using a condition like this to match but the response data matches both conditions:

if(myResponseData as personModel) {}
else if(myResponseData as placeModel) {}

Is there a condition that'll allow me to match a generic against a Type?

CodePudding user response:

I can propose two solutions:

Type predicates type predicates

Typescript playground using type predicates

Sample code

interface PersonModel {
    name: string;
    address: string;
}

interface PlaceModel {
    city: string;
    country: string;
}

const isPersonModel = (input: any): input is PersonModel => {
    const requiredProps: Array<keyof PersonModel> = ["name", "address"];
    return requiredProps.every(prop => input[prop] !== undefined);
}

const isPlaceModel = (input: any): input is PlaceModel => {
    const requiredProps: Array<keyof PlaceModel> = ["city", "country"];
    return requiredProps.every(prop => input[prop] !== undefined);
}

const person = { name: "Peter", address: "something"}; 
const place = { city: "London", country: "UK"};

console.log(`Is person a person: ${isPersonModel(person)}`);
console.log(`Is person a place: ${isPlaceModel(person)}`);

const genericInput = {};

if (isPersonModel(genericInput)) {
    //typescript believes it is a PersonModel
    const address = genericInput.address;
    const country = genericInput.name;
}

Using classes and instanceof operator

Playground here for classes

class PersonModel {
    constructor(public name: string, public address: string){}
}

class PlaceModel {
    constructor(public city: string, public country: string){}
}

const getObject = ():any => {
    if (Date.now() % 2 === 0) {
        console.log("generating person model");
        return new PersonModel("Peter", "Street 1");
    } else {
        console.log("generating place model");
        return new PlaceModel("Berlin", "Germany");
    }
}

const randomObject = getObject();

if (randomObject instanceof PlaceModel) {
    console.log("Object identified as Place model");
}
if (randomObject instanceof PersonModel) {
   console.log("Object identified as PersonModel");
}
  • Related