7

How can I set a superior class in TypeScript when collecting various different objects in one array that inherit from the same class so that TypeScript doesn't show an error?

I'm trying it like this:

interface IVehicle{
    modelName: string
}

interface ICar extends IVehicle{
    numberOfDoors: number,
    isDropTop: boolean
}

interface IBike extends IVehicle{
    hasDynamo: boolean
}


var vehicles: IVehicle[] =
    [
        {
            modelName: "carModelName", // Error
            numberOfDoors: 4,
            isDropTop: true
        },
        {
            modelName: "bikeModelName",
            hasDynamo: true
        }
    ]

Doing it this way, I'm getting errors.

I'm just able to add objects of the superior interface IVehicle if I don't want any errors shown.

0

1 Answer 1

15

After fixing the syntax errors, you can specify the type of each individual entry in the array.

interface IVehicle {
    modelName: string
}

interface ICar extends IVehicle {
    numberOfDoors: number,
    isDropTop: boolean
}

interface IBike extends IVehicle {
    hasDynamo: boolean
}

let vehicles: IVehicle[] =
    [
        {
            modelName: "carModelName",
            numberOfDoors: 4,
            isDropTop: true,
        } as ICar,
        {
            modelName: "bikeModelName",
            hasDynamo: true
        } as IBike
    ]

Or just change the type of the array to an array of vehicle, car or bike like this:

let vehicles: Array<IVehicle | ICar | IBike> =
    [
        {
            modelName: "carModelName",
            numberOfDoors: 4,
            isDropTop: true,
        },
        {
            modelName: "bikeModelName",
            hasDynamo: true
        }
    ]

If later you want to determine if an IVehicle is IBike or ICar you can use user defined type guards to do it.

function isBike(vehicle: IVehicle): vehicle is IBike {
    return (<IBike>vehicle).hasDynamo !== undefined;
}

function isCar(vehicle: IVehicle): vehicle is ICar {
    return (<ICar>vehicle).numberOfDoors !== undefined;
}

function log(vehicle: IVehicle) {
    if (isBike(vehicle)) {
        // tsc knows vehicle is IBike
        console.log(vehicle.hasDynamo);
    } else if (isCar(vehicle)) {
        // tsc knows vehicle is ICar
        console.log(vehicle.numberOfDoors);
    } else {
        console.log(vehicle.modelName);
    }
}

You can read more about them in the Advanced types section of the handbook.

You can also find a working example of the entire code in the playground here.

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you. Can I also cast IVehicle to ICar or IBike? For example when I fetch an object from that array.
there is no casting in typescript, only type assertions. If you need to find out which particular type an entry is you can use typeguards, I'll add an example for that.

Your Answer

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