Jeremy Thille Jeremy Thille - 1 month ago 10
TypeScript Question

Typescript - Better way to enforce an object's key type?

I'm trying to figure out the syntax to define a type (interface) of an object's key.

Couldn't find how to do it on StackOverflow or anywhere else.

I have crafted this method, it works but I find it clumsy. Is there any "official" syntax for it?

interface Report {
action: string;
exists?: boolean;
warnings? : string[];
errors? : string[];
}

let patent: Patent = {
numbers: { … },
dates : { … },
report: ( ():Report => ({ // This works, it enforces the key's type but looks ugly
action : "create",
exists : false,
otherKey : "otherValue" // Typescript detects this wrong key, that's good
}))()
}

Answer Source

It's not really clear what you're asking: you would define the type of the report property in the definition of Patent. So:

interface Report {
    action: string;
    exists?: boolean;
    warnings? : string[];
    errors? : string[];
}

class Patent {
  numbers: any;
  dates: any;
  report: Report;
}

let patent: Patent = {
        numbers: { },
        dates : { },
        report: {
            action : "create",
            exists : false,
            otherKey : "otherValue" // Typescript detects this wrong key, that's good
        }
}

gives you an error for otherKey just as you might have expected. The actual error is:

error TS2322: Type '{ numbers: {}; dates: {}; report: { action: string; exists: false; otherKey: string; }; }' is not assignable to type 'Patent'.
  Types of property 'report' are incompatible.
    Type '{ action: string; exists: false; otherKey: string; }' is not assignable to type 'Report'.
      Object literal may only specify known properties, and 'otherKey' does not exist in type 'Report'.

However it is worth noting that you'll only get that error for a literal value, as an object that simply implements an interface may have as many additional attributes as it wants, so the extra attributes wouldn't be a problem in that case.