javascript - Typescript array push-metoden kan ikke fange en tuppeltype av arrayen
const testArray:[number, string] = [10, 'test', 's'];
Det fungerer ikke.
const testArray:[number, string] = [10, 'test']; // It's been edited.
testArray.push('test');
Det fungerer.
Jeg tror den andre koden ikke skulle fungert.
Hvorfor fungerer den andre koden? Er det en feil?
-Lagt til-
Jeg har tenkt på problemet.
Kompilatoren kan bare fange feil under kompilering. Så kompilatoren fanger ikke feilen. Er det riktig?
Svar #1
Dette er et godt spørsmål, og jeg vil prøve å omformulere det så eksplisitt som mulig:
Tuplete typer er en type matrise med kjent lengde, hvor de forskjellige elementene kan ha forskjellige typer. En verdi av typen
[number, string]er garantert å ha enlengthpå2, med etnumberpå element0og enstringpå element1.Hvorfor tillater da TypeScript at du kaller metoder som
push(),pop(),shift(),unshift()ogsplice()på verdier av tupple-typer, når slike metoder generelt ødelegger de antatte garantiene for tupple-typer? Bør det ikke stoppe deg fra å gjøre det, akkurat som det stopper deg fra å tilordne en verdi som[1, "two", "three"]til[number, string]i utgangspunktet?
Ja, det er ikke bra.
Jeg vet ikke om det finnes et godt kanonisk svar på dette. Det nærmeste jeg kan finne er microsoft/TypeScript#6325, som foreslår at slike metoder bør utelates fra tuppeltyper. Dette forslaget ble avslått, muligens på grunn av at det ville være en brytende endring for eksisterende kode i virkelige prosjekter.
Et foreslått alternativ ser slik ut
type StrictTuple<T extends any[]> =
Omit<T, keyof (any[])> extends infer O ? { [K in keyof O]: O[K] } : never;
som ser mindre ut som et array og mer ut som et sett med numeriske nøkkel-egenskaper:
const x: StrictTuple<[number, string]> = [1, ""] // {0: number; 1: string }
x[1] = "okay";
x[0] = 123;
x.push(123); // error!
//~~~~ Property 'push' does not exist on type { 0: number; 1: string; }
Hvis du virkelig bryr deg om slike ting, kan det hende du vil bruke noe som StrictTuple ovenfor, men det er sannsynligvis mer bry enn det er verdt. Tuple-typer er allestedsnærværende i TypeScript, og hvis du bruker en form som ikke kan tildeles dem, må du gjennom mange uheldige hindringer for å bruke TypeScript.
Pragmatisk sett vil jeg si at du bare bør prøve å ikke endre tupler.
Det har vært noen nyere saker som refererer til microsoft/TypeScript#6325 som ber om å vurdere dette på nytt nå som tupler har blitt litt mer strenge i mellomtiden. Se microsoft/TypeScript#40316 og microsoft/TypeScript#48465, som er åpne, men ikke åpenbart populære. Det ville være en interessant øvelse å se hva som spesifikt ville bryte hvis push/pop/osv. ble utelatt fra tuplet-typer.
Lenke til kode på lekeplassen
Svar #2
[Fjernet forrige svar siden jeg misforstod.]
Ser ut som dette kan være et problem relatert til typeutvidelse? Du kan erklære tuplen din som readonly eller as const for å forhindre at push-funksjonen fungerer på tuplen i det hele tatt
const testArray:readonly [number, string] = [10, 'test'] as const;
testArray.push('test') // error
Jeg fant denne Medium-artikkelen om emnet: https://blog.logrocket.com/const-assertions-are-the-killer-new-typescript-feature-b73451f35802/
