Версия TypeScript: 3.3.0-dev.201xxxxx
Условия поиска:
Пересечение дженериков
Код
let connect = <R1,R2, R = R1&R2 >(mapState2Props: (state) => R1, mapDispatch2Props: (dispatch: any) => R2): R => {
let state = {};
let dispatch = () => { };
return { ...mapState2Props(state), ...mapDispatch2Props(dispatch)}
}
Ожидаемое поведение:
Я ожидал, что это будет действительным, потому что я определил R = R1&R2
в общей подписи.
Фактическое поведение:
Получить ошибку Type 'R1 & R2' is not assignable to type 'R'.
в операторе возврата. Я также пробовал R extends R1&R2
и получаю ту же ошибку.
Ссылка на игровую площадку:
Связанные вопросы:
Я считаю, что здесь ошибка правильная. Да, R1 & R2
можно присвоить по умолчанию R
, но R
может быть создан с конкретным типом _more_. Рассмотрим следующий экземпляр.
connect<{ x: number; }, { y: number; }, { x: number, y: number, z: number }>( ... );
Это действительный экземпляр R1
, R2
и R
, но R1 & R2
_не_ присваивается R
потому что в нем отсутствует z
параметр.
В вашем примере параметр R
самом деле не требуется (хотя ваш реальный вариант использования может быть более сложным). Это работает:
let connect = <R1,R2>(mapState2Props: (state) => R1, mapDispatch2Props: (dispatch: any) => R2): R1 & R2 => {
let state = {};
let dispatch = () => { };
return { ...mapState2Props(state), ...mapDispatch2Props(dispatch)}
}
хм, это хороший момент. Цель здесь заключалась в том, чтобы в конечном итоге добраться до того места, где вы могли бы просто указать тип возвращаемого значения R
и получить безопасность типа, что mapState2Props
& mapDispatch2Props
сочетании приведет к действительному R
Object.
НАПРИМЕР:
interface IComponentProps{
foo: string;
doFoo: ()=>void
}
let props: IComponentProps = connect<IComponentProps>(
(state) => { foo: state.foo },
(dispatch) => {doFoo: () => dispatch('FOO')}
)
Однако ... я не уверен, возможно ли это вообще ... Похоже, вам нужно вместо этого определить R1 и R2 как некоторое подмножество R
, но они зависят друг от друга ...
Обратите внимание, что R
также может быть совершенно не связанным типом. Аргументы типа по умолчанию в универсальных шаблонах не являются ограничениями.
connect<{ a: string }, { b: number }, { c: boolean[] }>(() => ({ a: "a" }), () => ({ b: 3 }))
Самый полезный комментарий
Я считаю, что здесь ошибка правильная. Да,
R1 & R2
можно присвоить по умолчаниюR
, ноR
может быть создан с конкретным типом _more_. Рассмотрим следующий экземпляр.Это действительный экземпляр
R1
,R2
иR
, ноR1 & R2
_не_ присваиваетсяR
потому что в нем отсутствуетz
параметр.В вашем примере параметр
R
самом деле не требуется (хотя ваш реальный вариант использования может быть более сложным). Это работает: