TypeScript: Type inference when using string literals

Viewed 63

Please have a look at the following TypeScript code. It's clear that the type inference behaves like described in the comments.

Now the question: Is it somehow possible to change the definition of type V2 = ... in a way, that it infers to type "someOtherValue" and not to string in general any longer?

As far as I understand TypeScript's type inference, this is absolutely NOT possible ... but who knows, maybe I am wrong. To be on the safe side I better ask the TypeScript community for help. Thanks.

const config1 = { value: 'someValue' as const } 

type K1 = keyof typeof config1      // type K1: "value" (not string in general)
type V1 = (typeof config1)['value'] // type V1: "someValue" (not string in general)

const config2 = { value: 'someOtherValue' } 

type K2 = keyof typeof config2      // type K2: "value" (not string in general)
type V2 = (typeof config2)['value'] // type V2: string

TypeScript Playground: Demo

2 Answers

you need to cast const on the whole config2 too.

const config2 = { value: 'someOtherValue' } as const;

otherwise it always will be string.


with the key access

const config1 = { value: 'someValue' as const } 

type K1 = keyof typeof config1      // type K1: "value" (not string in general)
type V1 = (typeof config1)['value'] // type V1: "someValue" (not string in general)

const config2 = { value: 'someOtherValue' } as const;

type K2 = keyof typeof config2 // type K2: "value" (not string in general)
type V2 = (typeof config2)[K2] // type V2: "someOtherValue"

Now the question: Is it somehow possible to change the definition of type V2 = ... in a way, that it infers to type "someOtherValue" and not to string in general any longer?

Yes, you have to tell typescript that type is not going to change with const assertion. You can either apply it to the value prop or the whole object as @satanTime suggested.

Why? Because typescript assumes you might do following thing.

const config2 = { value: 'someOtherValue' } 
config2.value = "something different"

With const assertion applied type checker can decide to do type narrowing.

const config1 = { value: 'someValue' as const } 
config1.value = "test" // Type '"test"' is not assignable to type '"someValue"'.
const config2 = { value: 'someOtherValue' } as const
config2.value = "test" // Cannot assign to 'value' because it is a read-only property.
Related