Je veux décrire une interface avec des objets imbriqués. Comment puis-je le faire sans créer d'interfaces pour les objets imbriqués?
interface ISome {
strProp:string;
complexProp:{
someStrKeyWhichIsDynamic:{
value:string;
optValue?:string;
}
};
}
J'ai aussi essayé (PD: ça va en fait)
interface ISome {
strProp:string;
complexProp:{
[someStrKeyWhichIsDynamic:string]:{
value:string;
optValue?:string;
}
};
}
Mais je ne peux pas assigner un objet comme
let dynamicStrKey = 'myKey';
{
strProp:'str',
complexProp:{
[dynamicStrKey]:{
value:'something here',
optValue: 'ok, that too',
}
};
à variable avec ISome
type sans assertion de type <ISome>
. Au moins WebStorm met en évidence cette affectation comme une erreur.
Comment décrire correctement les objets imbriqués?
Enfin, je pense que ma deuxième variante était correcte
interface ISome {
strProp:string;
complexProp:{
[someStrKeyWhichIsDynamic:string]:{
value:string;
optValue?:string;
}
};
}
Pour la clé dynamique, vous pouvez simplement écrire [dynamic:string]
pour spécifier qu'il y aura ici une propriété de chaîne. On dirait que j'ai eu une erreur webstorm qui n'était pas liée au problème.
BTW, si vous avez une énumération basée sur une chaîne, vous pouvez utiliser [key in MyEnum]: {...}
au lieu de [key:string]
. Cela résout l'erreur:
TS1337 un type de paramètre de signature d'index ne peut pas être un type d'union.
Et si vous avez un objet littéral, par exemple const obj = { prop1: 'blah', prop2: 'blahblah' }
Vous voudrez peut-être utiliser [key in keyof typeof obj]: {...}
pour décrire que votre clé dynamique ne peut être que "prop1" ou "prop2" (ou, plus générique, la valeur de Object.keys(obj
))
Il n'y a rien de mal avec vos deux premiers exemples. Ils compilent tous les deux très bien et pensent ce qu'ils disent.
Dans votre troisième exemple, vous voulez apparemment que le nom de la propriété soit "dynamique". Mais rappelez-vous, TS fonctionne au moment de la compilation. Au moment de la compilation, dynamicStrKey
n'a pas encore de valeur. Par conséquent, il est inutile d'essayer de l'utiliser comme nom de propriété dans une définition de type. Vous ne pouvez pas définir un artefact au moment de la compilation à l'aide d'une valeur au moment de l'exécution.
le code de la deuxième partie prend en charge les propriétés dynamiques.vous ne pouvez pas utiliser avec la dernière, car le type n'émet pas dans le code javascript.Je pense que vous aimez juste quelque chose ci-dessous, en utilisant plutôt générique.pour plus de détails, vous pouvez voir TypeScript types d'index .
interface ISome<K extends string> {
strProp: string;
complexProp: {
[P in K]: {
value: string;
optValue?: string;
}
};
}
let foo: ISome<"foo"> = {
strProp:"foo",
complexProp:{
foo:{
value:"foo"
}
}
};
let bar: ISome<"bar"> = {
strProp:"bar",
complexProp:{
bar:{
value:"bar",
optValue:"<optional>"
}
}
};
let foobar: ISome<"foo"|"bar"> = {
strProp:"foo",
complexProp:{
foo:{
value:"foo"
},
bar:{
value:"bar",
optValue:"<optional>"
}
}
};
// interesting things that use with any|never types
let anything:ISome<any|never>={
strProp:"foo",
complexProp:{}
};