DEV Community

Acid Coder
Acid Coder

Posted on • Edited on

Typescript WTF Moments 1: Mixing String Literal Key And String Key In Object Literal Type

This series is about confusions I encountered in Typescript, thing that is not intuitive, hard to reason with or require extra attention.

The cause of caveats may be due to bug or deficiency or just simply work as intended

I will add new posts to this series from time to time.

because Typescript has no negate type and without it, string cannot cover key that are not a1 and a2, string has to cover all keys.

type A = {[x:string]:1, a1:1, a2:2} // error: Property 'a2' of type '2' is not assignable to 'string' index type '1'.

type a = A['something'] // 1
//   ^?
type a1 = A['a1'] // 1
//   ^?
type a2 = A['a2'] // 2
//   ^?

const A:A={something:1, a1:1, a2:2} // error: Type '2' is not assignable to type '1'.

A.a2 = 2 // individual member write is ok
Enter fullscreen mode Exit fullscreen mode

so far so good, Typescript error suggestion prevent us from doing it in the wrong way

However there is a case it will by pass the first error, that is using intersection

type B = {[x:string]:1} & { b1:1, b2:2} // no error

type b = B['something']
//   ^?
type b1 = B['b1']
//   ^?
type b2 = B['b2']
//   ^?

const B:B={something:1, b1:1, b2:2} // error: Type '2' is not assignable to type '1'.

B.b2 = 2 // individual member write is ok
Enter fullscreen mode Exit fullscreen mode

playground

The type is correct when you read it but not when you write it, individual write however is fine

Top comments (0)