javascript - Skillnader mellan Record<string, any> och {}?
Den enda skillnaden jag ser är att du inte kan lägga till ytterligare egenskaper till {} men du kan till Record<string, any>. Är det något annat som jag missar?
Exempel på kod (länk till lekplats):
const one: Record<string, any> = { foo: 1 }
one.bar = 2
const two: {} = { foo: 1 }
two.bar = 2 // Property 'bar' does not exist on type '{}'.(2339)
Svar #1
Okej, så den verkliga frågan är varför vi kan tilldela vilket objekt som helst till {}. Detta handlar mer om språkdesignval. Språket är byggt över strukturell subtypkompatibilitet.
Typkompatibilitet i TypeScript baseras på strukturell undertypning. Strukturell typning är ett sätt att relatera typer enbart baserat på deras medlemmar. Detta står i kontrast till nominell typning.
Det betyder att vi kan tilldela till den mer lösa typen värden av dess subtyper. I din kod är {} den bredaste objekttypen, vi kan säga att det är föräldratypen för varje objekttyp, med andra ord är varje annan objekttyp en subtyp av {}. Nedan är några exempel på kontroller:
type ISubTypeOfEmptyObj<T> = T extends {} ? true : false
type Check1 = ISubTypeOfEmptyObj<{bar: 2}> // yes it is
type Check2 = ISubTypeOfEmptyObj<{foo: 2, bar: 'a'}> // yes it is
type Check3 = ISubTypeOfEmptyObj<number> // surprisingly that is also true
const a: {} = 1; // no error 😱
Vad bevisar det - faktumet att du kan skapa en instans av {} nästan ur tomma intet (endast null och undefined-värden kan inte vara medlemmar i {}). Men det gäller också att efter initialisering kan du inte bara sätta några egenskaper till ett sådant värde, eftersom typen säger att det inte finns några. Med andra ord kan du skapa {} av nästan vad som helst, men du kan endast använda det som ett tomt objekt efteråt.
Record<string, any> är en striktare typ än {}, till exempel kommer varje arraytyp att kunna tilldelas {}, men kan inte tilldelas Record<string, any>. Detsamma gäller för andra typer som string eller number. Record<string, any> representerar alla objekt med valfria strängegenskaper, därför kan du lägga till vilken strängegenskap som helst till objektet, eftersom typen tillåter det.
Svar #2
Typen {} matchar endast ett tomt objekt.
Record<string, any> skulle vara liknande { [key: string]: any}
UPPDATERING: Min första mening var falsk. Typen {} matchar ungefär vad som helst som nämns i det accepterade svaret
