Gibb Sonn
Gibb Sonn

Reputation: 459

Why does typescript not recognise that the keys of a generic are of type string?

Here's a contrived example to demonstrate the issue

function funcWithGeneric<T extends Record<string, any>>(propertyName: keyof T){
    propertyName.toUpperCase() 
    // ^ Errors with
    // Property 'toUpperCase' does not exist on type 'string | number | symbol'.
    // Property 'toUpperCase' does not exist on type 'number'.(2339)
}

I assumed that the Record<string part would be enough to tell Typescript that the propertyName will be of a string type but apparently not.

Why is this?

Upvotes: 0

Views: 179

Answers (1)

dsalex1
dsalex1

Reputation: 464

While T does have to extend Record<string,any> it isn't limited to properties having only string as keys.

consider:

const test: Record<string, any> = {
  a:"test",
  [3]:"test"
}

this is a valid assignment, while keyof test essentially is string|number

Is there a reason why you have T as a generic while you don't use in the function definition?

what you can do is something like

function funcWithGeneric<T extends Record<K, any>, K extends string>(propertyName: K){
    propertyName.toUpperCase() 
}

funcWithGeneric("test")

funcWithGeneric(4)

Playground

Upvotes: 2

Related Questions