Versão TypeScript: 3.3.0-dev.201xxxxx
Termos de pesquisa:
Intersecção 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)}
}
Comportamento esperado:
Eu esperaria que isso fosse válido porque eu defini R = R1&R2
na assinatura genérica.
Comportamento real:
Obtenha um erro Type 'R1 & R2' is not assignable to type 'R'.
na instrução de retorno. Também tentei R extends R1&R2
e recebo o mesmo erro.
Link Playground:
Assuntos relacionados:
Eu acredito que o erro está correto aqui. Sim R1 & R2
ser atribuído ao padrão de R
, mas R
pode ser instanciado com um tipo _mais_ específico. Considere a seguinte instanciação.
connect<{ x: number; }, { y: number; }, { x: number, y: number, z: number }>( ... );
Esta é uma instanciação válida de R1
, R2
e R
, mas R1 & R2
é _não_ atribuível a R
porque está faltando o Parâmetro z
.
Em seu exemplo, o parâmetro R
não é realmente necessário (embora seu caso de uso real possa ser mais complicado). Isso 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 isso é um bom ponto. O objetivo aqui era chegar onde você poderia apenas especificar o tipo de retorno R
e obter segurança de tipo que mapState2Props
& mapDispatch2Props
combinados resultariam em um R
válido
POR EXEMPLO:
interface IComponentProps{
foo: string;
doFoo: ()=>void
}
let props: IComponentProps = connect<IComponentProps>(
(state) => { foo: state.foo },
(dispatch) => {doFoo: () => dispatch('FOO')}
)
No entanto ... Não tenho certeza se isso é mesmo possível ... Parece que você precisaria definir R1 e R2 como algum subconjunto de R
, mas eles são dependentes um do outro ...
Observe que R
também pode ser um tipo completamente não relacionado. Os argumentos de tipo padrão em genéricos não são restrições.
connect<{ a: string }, { b: number }, { c: boolean[] }>(() => ({ a: "a" }), () => ({ b: 3 }))
Comentários muito úteis
Eu acredito que o erro está correto aqui. Sim
R1 & R2
ser atribuído ao padrão deR
, masR
pode ser instanciado com um tipo _mais_ específico. Considere a seguinte instanciação.Esta é uma instanciação válida de
R1
,R2
eR
, masR1 & R2
é _não_ atribuível aR
porque está faltando o Parâmetroz
.Em seu exemplo, o parâmetro
R
não é realmente necessário (embora seu caso de uso real possa ser mais complicado). Isso funciona: