loone96
loone96

Reputation: 849

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

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?

Upvotes: 3

Views: 911

Answers (1)

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

Upvotes: 5

Related Questions