typescript - Finnes det et alternativ for å gjøre spredning av et objekt strikt?


Jeg lurte på om det finnes en kompilatorvalg eller noe lignende for å gjøre spredning av objekter streng.

Vennligst se følgende eksempel for å forstå hva jeg mener:

interface Foo {
  a: string;
}

interface Bar {
  a: string;
  b: number;
}

const barObject: Bar = { a: "a string", b: 1 };

// should give a warning because Bar has more properties (here b) than Foo
const fooObject: Foo = { ...barObject };

// actually prints 1
console.log((fooObject as any).b); 

Er noe sånt mulig?

Svar #1

Interessant spørsmål. I henhold til dette problemet er resultatet av spredningsoperatoren ment å ikke utløse sjekk av overflødige egenskaper.

// barObject has more props than Foo, but spread does not trigger excess property checks
const fooObject: Foo = { ...barObject };

// b is explicit property, so checks kicks in here
const foo: Foo = { ...bar, b: 2 }

Det finnes ikke eksakte typer for TypeScript for øyeblikket, men du kan lage en enkel typetest for å håndheve streng objektspredning:

// returns T, if T and U match, else never
type ExactType<T, U> = T extends U ? U extends T ? T : never : never

const bar: Bar = { a: "a string", b: 1 };
const foo: Foo = { a: "foofoo" }

const fooMergeError: Foo = { ...bar as ExactType<typeof bar, Foo> }; // error
const fooMergeOK: Foo = { ...foo as ExactType<typeof foo, Foo> }; // OK

Med en hjelpefunksjon kan vi redusere redundans litt:

const enforceExactType = <E>() => <T>(t: ExactType<T, E>) => t

const fooMergeError2: Foo = { ...enforceExactType<Foo>()(bar) }; // error

Kodeeksempel

Relaterte artikler