javascript - Typescript și transformarea textului (toLowerCase) îmi pierde tipul


Reproducerea simplă a problemei mele:

const demo = {
    aaa: 'aaa',
    bbb: 'bbb',
}

const input = 'AAA'

console.log(demo[input.toLowerCase()])

Teren de joacă

JS în sine va funcționa. Va schimba 'AAA' în 'aaa', care există în obiectul demo. Dar TS generează o eroare:

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ aaa: string; bbb: string; }'.

Este pentru că vede această valoare ca orice șir de caractere, nu 'aaa'. Deci TS nu permite nicio transformare de text în compilatorul său?

Această valoare cu majuscule provine din API (enum GraphQL), așa că nu pot să o schimb. Pe de altă parte, acest obiect provine dintr-o bibliotecă care folosește chei normale în PascalCase. Deci, cum pot conecta ambele fără ca TS să reclame?

Răspuns #1

Ceea ce vrei cu adevărat să susții este că input.toLowerCase() rezultă într-o cheie validă pentru harta demo. Poți exprima asta astfel:

console.log(demo[input.toLowerCase() as keyof typeof demo])

Acest lucru ar trebui să-ți ofere siguranță completă a tipurilor în codul din jur. Acesta este în regulă:

let ok: 'aaa' | 'bbb' = demo[input.toLowerCase() as keyof typeof demo]

Dar acestea sunt respinse:

let error1: 'aaa' = demo[input.toLowerCase() as keyof typeof demo]
let error2: 'ccc' = demo[input.toLowerCase() as keyof typeof demo]

Răspunsul #2

În plus față de ceea ce a spus @Thomas în răspunsul de mai sus,

Ori de câte ori folosești Typescript, ar trebui să definești clar tipurile variabilelor și obiectelor.

Verifică codul de mai jos.

type d = {
    [key: string]: string
}

const demo: d = {
    aaa: 'aaa',
    bbb: 'bbb',
}

const input: string = 'AAA'

console.log(demo[input.toLowerCase()])