Sten
Sten

Reputation: 1109

Typescript type annotation for object property on initialisation

Is it possible to do a type annotation for a specific property when initialising an object in Typescript?

In my case I have a template literal type

type ID = `book#${string}`;

and I want to make sure that when I create an object (which needs to be of type Record<string, any>, so I cannot enforce type there):

const a = {
  id: `book#abc` # Should be fine
}

that there is a lint / compile time error if I write for example

const a = {
  id: `car#abc` # Should NOT be fine
}

I am looking for something along the lines of

const a = {
  id: `book#abc` as ID
}

but that would just assume (assert?) that the id is correct.

The only solution I have found is to create a function

function asId(x: ID): ID {
  return x;
}

which I don't find very nice.

Upvotes: 1

Views: 407

Answers (1)

T.J. Crowder
T.J. Crowder

Reputation: 1074485

This answer might violate this constraint

...which needs to be of type Record<string, any>, so I cannot enforce type there...

but I don't think so (details below).

You could define a WithID type like this:

type WithID = {id: ID} & Record<string, any>;

That enforces the requirement on id while allowing other properties:

const a: WithID = {
    id: `book#abc`,  // Works
    whatever: 42,
};
const b: WithID = {
    id: `car#abc`,  // Type error
    whatever: 42,
};

The reason I don't think it violates the constraint I quoted above is that a and b can be used anywhere a Record<string, any> can be used. Example:

function usageExample(o: Record<string, any>) {
    console.log(o);
}
usageExample(a); // Works

// And

const c: Record<string, any> = a; // Works

So the id being "tighter" really just applies to the object literal you're assigning.

Playground link

Upvotes: 1

Related Questions