Versión de TypeScript: 3.3.0-dev.201xxxxx
Términos de búsqueda:
Intersección de genéricos
Código
let connect = <R1,R2, R = R1&R2 >(mapState2Props: (state) => R1, mapDispatch2Props: (dispatch: any) => R2): R => {
let state = {};
let dispatch = () => { };
return { ...mapState2Props(state), ...mapDispatch2Props(dispatch)}
}
Comportamiento esperado:
Esperaría que esto fuera válido porque he definido R = R1&R2
en la firma genérica.
Comportamiento real:
Obtiene un error Type 'R1 & R2' is not assignable to type 'R'.
en la declaración de devolución. También probé R extends R1&R2
y obtengo el mismo error.
Enlace de patio de recreo:
Asuntos relacionados:
Creo que el error es correcto aquí. Sí, R1 & R2
se puede asignar al valor predeterminado de R
, pero se puede crear una instancia de R
con un tipo _más_ específico. Considere la siguiente instanciación.
connect<{ x: number; }, { y: number; }, { x: number, y: number, z: number }>( ... );
Esta es una instanciación válida de R1
, R2
y R
, pero R1 & R2
es _no_ asignable a R
porque falta el z
parámetro.
En su ejemplo, el parámetro R
no es realmente necesario (aunque su caso de uso real puede ser más complicado). Esto funciona:
let connect = <R1,R2>(mapState2Props: (state) => R1, mapDispatch2Props: (dispatch: any) => R2): R1 & R2 => {
let state = {};
let dispatch = () => { };
return { ...mapState2Props(state), ...mapDispatch2Props(dispatch)}
}
hmm ya ese es un buen punto. El objetivo aquí era eventualmente llegar a donde podría simplemente especificar el tipo de retorno R
y obtener seguridad de tipo que mapState2Props
& mapDispatch2Props
combinados daría como resultado un R
válido
P.EJ:
interface IComponentProps{
foo: string;
doFoo: ()=>void
}
let props: IComponentProps = connect<IComponentProps>(
(state) => { foo: state.foo },
(dispatch) => {doFoo: () => dispatch('FOO')}
)
Sin embargo ... no estoy seguro de si eso es posible ... Parece que, en su lugar, necesitaría definir R1 y R2 como un subconjunto de R
, pero dependen el uno del otro ...
Tenga en cuenta que R
también podría ser un tipo completamente ajeno. Los argumentos de tipo predeterminado en genéricos no son restricciones.
connect<{ a: string }, { b: number }, { c: boolean[] }>(() => ({ a: "a" }), () => ({ b: 3 }))
Comentario más útil
Creo que el error es correcto aquí. Sí,
R1 & R2
se puede asignar al valor predeterminado deR
, pero se puede crear una instancia deR
con un tipo _más_ específico. Considere la siguiente instanciación.Esta es una instanciación válida de
R1
,R2
yR
, peroR1 & R2
es _no_ asignable aR
porque falta elz
parámetro.En su ejemplo, el parámetro
R
no es realmente necesario (aunque su caso de uso real puede ser más complicado). Esto funciona: