Typescript: A intersecção de dois parâmetros genéricos para formar um terceiro não é reconhecida como equivalente

Criado em 13 jan. 2019  ·  3Comentários  ·  Fonte: microsoft/TypeScript


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:

Ligação

Assuntos relacionados:

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

Question

Comentários muito úteis

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)}
}

Todos 3 comentários

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 }))
Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

CyrusNajmabadi picture CyrusNajmabadi  ·  3Comentários

seanzer picture seanzer  ·  3Comentários

kyasbal-1994 picture kyasbal-1994  ·  3Comentários

uber5001 picture uber5001  ·  3Comentários

siddjain picture siddjain  ·  3Comentários