2017-07-25 77 views
1

由于泛型推断的更改,我看到现有的TypeScript代码中断。TypeScript 2.4泛型导致编译错误的推论

例子:

interface Action { 
    type: string; 
} 
interface MyAction extends Action { 
    payload: string; 
} 
interface MyState {} 

type Reducer<S> = <A extends Action>(state: S, action: A) => S; 

const myReducer: Reducer<MyState> = (state: MyState, action: MyAction) => { 
    if (action.type === "MyActionType") { 
     return {}; 
    } 
    else { 
     return {}; 
    } 
}; 

而且编译错误:

Error:(11, 7) TS2322:Type '(state: MyState, action: MyAction) => {}' is not assignable to type 'Reducer<MyState>'. 
    Types of parameters 'action' and 'action' are incompatible. 
    Type 'A' is not assignable to type 'MyAction'. 
     Type 'Action' is not assignable to type 'MyAction'. 
     Property 'payload' is missing in type 'Action'. 

回答

1
interface MyOtherAction { 
    type: 'MyOtherActionType' 
    foo: number 
} 

declare const state: State 
declare const myOtherAction: MyOtherAction 

// the following is a valid call according to myReducer's signature 
myReducer(state, myOtherAction) 

但是已分配给myReducer值不接受每一种行为的,所以你得到一个错误。

没有理由让第二个参数具有通用性,因为您没有在两个参数/返回值之间创建约束。只要做到

type Reducer<S> = (state: S, action: Action) => S; 
+2

注给任何人来到这里,这只是工作,因为打字稿对待非通用的非功能参数,双变(见[讨论](https://github.com/Microsoft/TypeScript/issues/14973 ))。 'myReducer()'认为'action'参数的类型为'MyAction'仍然不安全。为了安全起见,'myReducer'的第二个参数应该被键入为Action,或者'Reducer'类型应该被声明为'类型Reducer (state:S,action:A )=> S;'和'myReducer'的类型是'Reducer '。 – jcalz

+0

@jcalz这就是我最终为简单减速器所做的事情,但是,它不适用于Redux附带的类型。值得一提的是,这已经在Redux类型中得到修复,在这些类型中,他们添加了一个名为AnyAction的扩展Action类型,其索引签名为:[[index:string]:any'。编辑:如果可以更新Redux类型(即ActionCreator,Dispatch,Store等)以允许此约束Reducer示例,那将会很整洁。 – Ngz