Typescript readonly typed class doesn't collide with regular typescript class if the structure is the same

99 views Asked by At

I know typescript has a structural typing mechanism. I would expect however, that if you have a class like this:

class Country {
    id: string;
    name: string;
}

and one defined like this:

class ReadonlyCountry {
    readonly id: string;
    readonly name: string;     
}

that the typing system would show collisions if you return an object with the ReadonlyCountry type in a function that has as return type Country. It appears this is not the case as in the typescript playground example shown below.

class Country {
    id: string;
    name: string;
}

class ReadonlyCountry {
    readonly id: string;
    readonly name: string;    
}

function select(value: string): ReadonlyCountry[] {
    let country = new Country();
    country.id = "1";
    country.name = "name";
    return [country]; 
}

function select2(value: string): Country[] {
    // the type of the return here will be ReadonlyCountry[]
    // the type of the function return here is Country[]
    // why doesn't this collide?
    return select(value);
}

So my question is, how can I make sure that a type which has readonly properties and a type which does not have readonly types, and which are structurally the same, show type errors when mixed? Am I missing something stupid here and is it just the structural typing which causes this to happen?

Any help would be appreciated.

1

There are 1 answers

3
Amid On

Yes it is a structural typing that cause your problems. I think you should reconsider the structure of your classes and try avoid those with identical structure that must be treated differently.

As a side note. Instead of creating the read-only versions of the same classes (thus duplicating your code and introducing maintenance headache) why not to use mapped types (see here), and specifically Readonly one already predefined for you:

function select(value: string): Readonly<Country>[]

Hope this helps.