Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeScript Error: Getter-only property not defined in literal

Tags:

typescript

This feels like a really dumb error, but I have a typescript class:

export class Stat{
    abbr: StatType;
    score: number;
    mod: number;
    get name(): string { return StatType[this.abbr]; }
}

The "name" property is read-only, right?

However, while dummying up some "stats", I get the error that I'm not defining "name".

const stats: Stat[] = [{
    abbr: StatType.Str,
    score: 15,
    mod: 2
}]

Which produces the error: error TS2741: Property 'name' is missing in type '{ abbr: StatType.Str; score: number; mod: number; }' but required in type 'Stat' But if the property "name" is read-only, why do I have to assign it a value?

And IF I assign a value, then that value is used, the get() property is ignored entirely.

Am I doing something wrong? How do I convince TS that I don't need to provide a name property?

The enum is defined thusly:

export enum StatType{
    Str,
    Dex,
    Con,
    Int,
    Wis,
    Cha
}

Thanks!

like image 708
emery.noel Avatar asked Nov 06 '22 19:11

emery.noel


1 Answers

LAST EDIT: Well, so technically the edit answer works, but the object isn't transformed into a Stat, so it doesn't get the implementation of the getter. It "works" (as far as TS is concerned), but the getter is undefined, unless I manually add it in to the object. (My browser must have had a dirty cache or something.)

So what I ended up doing was creating a "mock" service that can stub out objects for me. I don't have to inject it into any classes or anything, I can declare it outside the class (just new it up), and use it to generate the objects I want. This gives me: the ability to have my actual objects (with getters), an empty constructor for my objects, and I'm not dirtying up my service class (though I am dirtying up the file ... which I can clean when I implement http).

... At this point, it probably would have just been faster to implement http.

EDIT: Ok so HERE is the real answer: just cast the json object. If I do that I don't need to define a constructor just for test data, and I don't need to define every property/function.

let statTest = <Stat>({
    abbr: StatType.Con,
    score: 12,
    mod: 1
});

Original Answer:

So it turns out that you need to actually create the objects, using new() syntax. But since TS lacks initializer lists, you have to create an explicit constructor, and manually provide all the arguments.

So my class became:

export class Stat{
    abbr: StatType;
    score: number;
    mod: number;
    constructor(statType: StatType, score: number, mod: number){
        this.abbr = statType;
        this.score = score;
        this.mod = mod;
    }
    get name(): string { return StatType[this.abbr]; }
}

And my array became:

const stats: Stat[] = [
    new Stat(StatType.Str, 15, 2)
]

Oh well, I don't think this will matter when values come from an actual server.

like image 110
emery.noel Avatar answered Nov 15 '22 12:11

emery.noel