Typescript: L'intersection de deux paramètres génériques pour en former un troisième n'est pas reconnue comme équivalente

Créé le 13 janv. 2019  ·  3Commentaires  ·  Source: microsoft/TypeScript


Version TypeScript: 3.3.0-dev.201xxxxx


Termes de recherche:

Intersection de génériques

Code

let connect = <R1,R2, R = R1&R2 >(mapState2Props: (state) => R1, mapDispatch2Props: (dispatch: any) => R2): R => {
  let state = {};
  let dispatch = () => { };
  return { ...mapState2Props(state), ...mapDispatch2Props(dispatch)}
}

Comportement prévisible:
Je m'attendrais à ce que ce soit valide car j'ai défini R = R1&R2 dans la signature générique.

Comportement réel:

Obtenez une erreur Type 'R1 & R2' is not assignable to type 'R'. sur la déclaration de retour. J'ai également essayé R extends R1&R2 et j'obtiens la même erreur.

Lien Playground:

Lien

Problèmes liés:

https://github.com/Microsoft/TypeScript/issues/5823

Question

Commentaire le plus utile

Je pense que l'erreur est correcte ici. Oui R1 & R2 est assignable à la valeur par défaut de R , mais R peut être instancié avec un type spécifique _more_. Considérez l'instanciation suivante.

connect<{ x: number; }, { y: number; }, { x: number, y: number, z: number }>( ... );

Il s'agit d'une instanciation valide de R1 , R2 et R , mais R1 & R2 n'est _pas_ assignable à R car il manque le Paramètre z .

Dans votre exemple, le paramètre R n'est pas réellement requis (bien que votre cas d'utilisation réel puisse être plus compliqué). Cela marche:

let connect = <R1,R2>(mapState2Props: (state) => R1, mapDispatch2Props: (dispatch: any) => R2): R1 & R2 => {
  let state = {};
  let dispatch = () => { };
  return { ...mapState2Props(state), ...mapDispatch2Props(dispatch)}
}

Tous les 3 commentaires

Je pense que l'erreur est correcte ici. Oui R1 & R2 est assignable à la valeur par défaut de R , mais R peut être instancié avec un type spécifique _more_. Considérez l'instanciation suivante.

connect<{ x: number; }, { y: number; }, { x: number, y: number, z: number }>( ... );

Il s'agit d'une instanciation valide de R1 , R2 et R , mais R1 & R2 n'est _pas_ assignable à R car il manque le Paramètre z .

Dans votre exemple, le paramètre R n'est pas réellement requis (bien que votre cas d'utilisation réel puisse être plus compliqué). Cela marche:

let connect = <R1,R2>(mapState2Props: (state) => R1, mapDispatch2Props: (dispatch: any) => R2): R1 & R2 => {
  let state = {};
  let dispatch = () => { };
  return { ...mapState2Props(state), ...mapDispatch2Props(dispatch)}
}

hmm ya c'est un bon point. Le but ici était d'arriver finalement à l'endroit où vous pouviez simplement spécifier le type de retour R et obtenir une sécurité de type que mapState2Props & mapDispatch2Props combinée donnerait un R valide

PAR EXEMPLE:

interface IComponentProps{
  foo: string;
  doFoo: ()=>void
}
let props: IComponentProps = connect<IComponentProps>(
  (state) => { foo: state.foo },
  (dispatch) => {doFoo: () => dispatch('FOO')}
)

Cependant ... je ne suis pas sûr que cela soit même possible ... Il semble que vous deviez définir à la place R1 & R2 comme un sous-ensemble de R , mais ils dépendent les uns des autres ...

Notez que R pourrait également être un type totalement indépendant. Les arguments de type par défaut dans les génériques ne sont pas des contraintes.

connect<{ a: string }, { b: number }, { c: boolean[] }>(() => ({ a: "a" }), () => ({ b: 3 }))
Cette page vous a été utile?
0 / 5 - 0 notes