July.Tech July.Tech - 4 months ago 31
TypeScript Question

In Typescript, why am I required to set the property of a class that is defined as read-only?

I have the following class definition:

class Department
{
name: string;
id: string;

get prefix(): string
{
return !isNaN(parseFloat(this.id)) ? "n" : "i" ;
}
}


Elsewhere in my code, I try to use it like this:

getDepartmentList(): Department[] {
return [
{
"name": "Dept 1",
"id": "1000"
}
];
}


However, I get the following error:


Type '{ "name": string; "id": string; }' is not assignable to type
'Department'. Property 'prefix' is missing in type '{ "name": string;
"id": string; }'.


I am sure the real problem is my lack of understanding of Typescript, but can someone explain why the compiler sees the getter function as a property and expects me to set a value on it?

Answer

Your class Department is creating a type Department. You are defining that to contain name, id and prefix. The objects you return in getDepartmentList does not contain the prefix, so they are not structurally compatible with the type Department. Hence you get an error.

I guess that you assume that the prefix-property will be available on anything do declare to be of the type Department. This is not the case, there is no kind of dynamic class assignments like that in typescript. You have to make sure yourself that objects that you say is certain type, actually fulfill that type.

You could do it something like this:

class Department
{
    constructor(public name:string, public id:string){ }

    get prefix(): string
    {
        return  !isNaN(parseFloat(this.id)) ? "n" : "i" ;
    }
}

function getDepartmentList(): Department[]
{
    return [new Department("Dept 1", "1000")];
}

Here you are instantiating new objects from the Department class, hence those objects will all have the prefix property.

The use of the access modifier in the constructor signature is telling typescript to create a property of that parameter, instead of only being treated as an argument.

It's equivalent to:

class Department
{
    name: string;
    id:string;

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

    get prefix(): string
    {
        return  !isNaN(parseFloat(this.id)) ? "n" : "i" ;
    }
}