typescript - Hur hanterar jag en typ som bör initieras som ett tomt objekt innan HTTP-förfrågningar?


Så jag har en definierad typ

export type User = {
  id: string
  [prop: string]: any
}

och jag behöver att denna typ också ska kunna lagra ett tomt objekt.

Men om jag försöker något sådant:

const user: User = {}

Jag får felet

Egenskapen 'id' saknas i typen '{}' men krävs i typen 'User'.ts(2741)

Jag behöver sätta user som ett tomt objekt, eftersom det bara fylls på efter en HTTP-förfrågan.

Jag vet att jag kan använda:

const user: User = {} as User

Men jag undrar om detta är det enda sättet, måste jag skriva {} as User varje gång jag sätter användarvariabeln som ett tomt objekt? Eller finns det bättre sätt att göra det?

Hur hanterar jag dessa situationer?

Svar #1

Vi vill använda en unionstyp som kombinerar ett tomt objekt och ett annat gränssnitt. Nu säger ett enkelt val att du borde använda type Final=IFace |{} men det skulle vara fel.

Egentligen beter sig typen tomt objekt konstigt i TypeScript där du kan använda det för att representera många saker. Läs detta.

Citerar från artikeln:

Den tomma objekttypen i TypeScript beter sig inte riktigt som du förväntar dig. Den representerar inte "vilket objekt som helst". Istället representerar den vilket värde som helst som inte är null eller undefined.

Därför är det därför om du gör något som:

export type IncorrectUserType = {
  id: string
  [prop: string]: any
} | {};

const x1: IncorrectUserType = {};
const y1: IncorrectUserType = 'x'; //This will not throw an error

Vi vill inte ha det. Och det är därför vi skapar vår egen typ för tomt objekt:

type EmptyObj = Record<PropertyKey, never>;

export type User = {
  id: string
  [prop: string]: any
} | EmptyObj;


const x2: User = {};
const y2: User = 'x'; //Throws an error

Här är lekplatslänken för dig att prova.

Här är en Github-tråd som diskuterar samma problem. Du kanske upptäcker att det inte finns något VERKLIGT sätt att skriva ett tomt objekt i TS, och varje metod kan ha någon brist

Svar #2

Du kan använda en union med ett tomt objekt.

export type User = {
  id: string
  [prop: string]: any
} | {}

Var medveten om att det kommer att påverka dina befintliga användningar eftersom det inte kommer att veta om det nu är det "fullständiga" objektet eller ett tomt. Överväg att lämna din User-typ som den är och skapa en OptionalUser eller någon version och särskilja den till User över någon domängräns.