2 votes

Comment déduire correctement les signatures d'index ?

Il semble que l'inférence de l'arg d'entrée à une signature d'index générique ne fonctionne pas comme prévu (ou alors j'ai raté quelque chose).

Comment puis-je faire en sorte que le type de retour soit déduit et que la saisie soit validée correctement ?

interface Styles {
  contentAlign?: string;
  zIndex?: number;
}

function createTheme<S extends { [key: string]: Styles }>(theme: S) {
  return theme;
}

// this works, foo is marked as invalid
const style: Styles = {
  zIndex: 1,
  foo: 'bar', // <-- invalid
};

// once I try to use the Styles as index signature it allows other properties
const t = createTheme({
  Button: {
    zIndex: 1,
    foo: 'bar', // <-- valid??
  },
});

J'attends Type { foo: "bar" } is not assignable to type Styles mais il semble qu'il s'agisse d'une entrée valide

1voto

devilmaster Points 439

S extends { [key: string]: Styles } signifie que S peut être un sous-type de { [key: string]: Styles } . Mais cela implique également que toute propriété de S peut également être un sous-type de Styles Cela signifie donc qu'une clé donnée peut en fait avoir plus de propriétés que celles spécifiées dans la rubrique Styles .

Généralement, en POO, il est permis d'assigner un sous-type là où un type de base est attendu. Typescript n'effectue des contrôles de propriété excessifs que lorsque des objets littéraux sont directement assignés à un type spécifique. Lors de l'affectation à un paramètre de type générique, le compilateur n'effectue pas de contrôles de propriétés excessifs car il suppose que vous souhaitez autoriser les sous-types. S extends {...} lit n'importe quel type S qui étend {...} ).

Dans votre cas, puisque vous voulez autoriser toutes les clés, mais que vous ne voulez pas désactiver les vérifications de propriétés excessives de Styles J'utiliserais comme paramètre de type les clés de l'objet au lieu de l'objet entier :

interface Styles {
  contentAlign?: string;
  zIndex?: number;
}

function createTheme<K extends PropertyKey>(theme: Record<K, Styles>) {
  return theme;
}

// this works, foo is marked as invalid
const style: Styles = {
  zIndex: 1,
  foo: 'bar', // <-- invalid
};

// once I try to use the Styles as index signature it allows other properties
const t = createTheme({
  Button: {
    zIndex: 1,
    foo: 'bar', // <-- error
  },
  Header: {
    zIndex: 1,
    foo: 'bar', // <-- error
  },
});

Jouer

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X