TypeScript: How to give naming rules to a dynamic key(property)?

Issue

Let’s say object could be looking like this depending on the response…

//CASE 1
const response1 = {
    id: 1,
    name: 'foo',
    isAdmin: true,
}

//CASE 2
const response2 = {
    id: 1,
    name: 'foo',
    isAdmin: true,
    property1: 'any string...'
}

//CASE 3
const response3 = {
    id: 1,
    name: 'foo',
    isAdmin: true,
    property1: 'any string...',
    property2: 'any string...'

}

Properties ‘id’, ‘name’, ‘isAdmin’ are required and property + ‘integer value’ can be optional. For example, property123, property10 can be property to an object.

I’m a newbie to typescript world so I can only think of using index signature.

interface IResponse {
    [property: string]: number | string | boolean;
    id: number;
    name: string;
    isAdmin: boolean;
}

const response1: IResponse = {
    id: 1,
    name: 'foo',
    isAdmin: true,
}

const response2: IResponse = {
    id: 1,
    name: 'foo',
    isAdmin: true,
    property1: 'any string...'
}

const response3: IResponse = {
    id: 1,
    name: 'foo',
    isAdmin: true,
    property1: 'any string...',
    property2: 'any string...'

}

It doesn’t throw any errors but there’s problems.

  1. I don’t want any properties to be assigned to an object except satisfying naming rules like "property+ ‘integer’".
//This should be throuwing an error.
const response4: IResponse = {
    id: 1,
    name: 'foo',
    isAdmin: true,
    grade: 'A'

}
  1. TypeScript can’t infer or autocomplete property1, property2 ….

Is there any better solution to typing this object to solve this problems?

Solution

UPDATED after @loone96 comment. My bad

It is possible since typescript 4.4, symbol-and-template-string-pattern-index-signatures

Please try this:

interface IResponse {
    id: number;
    [property: `property${number}`]: string | boolean;
    name: string;
    isAdmin: boolean;
}

const response1: IResponse = {
    id: 1,
    name: 'foo',
    isAdmin: true,
    grade: 'A' // error
}

const response2: IResponse = {
    id: 1,
    name: 'foo',
    isAdmin: true,
    property: '2' // expected error
}

const response3: IResponse = {
    id: 1,
    name: 'foo',
    isAdmin: true,
    property2: 2 // expected error
}

const response4: IResponse = {
    id: 1,
    name: 'foo',
    isAdmin: true,
    property2: 'str' // ok
}

Playground

Answered By – captain-yossarian

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published