扩展语法是不是会创建误报类型安全返回的对象?

Posted

技术标签:

【中文标题】扩展语法是不是会创建误报类型安全返回的对象?【英文标题】:Does the spread syntax creates a false positive typesafe returned object?扩展语法是否会创建误报类型安全返回的对象? 【发布时间】:2019-12-06 18:08:38 【问题描述】:

我最近正在为 redux 编写一个 reducer,而给定操作的有效负载值将覆盖其状态。当我注意到我的减速器没有返回我期望的对象并且打字稿没有抱怨它时,一个错误让我回到了我的代码。

interface State 
    value: number;


interface Action 
    type: string;
    payload: 
        value: number;
    


const reducer = (state: State, action: Action): State => 
    switch (action.type) 
        case "CORRECT_SHAPE":
            return 
                ...state,
                ...action.payload
            
        case "INCORRECT_BUT_WARNED":
            return 
                ...state,
                otherprop: "boom!" // will correctly flag incoherent property
                
       case "INCORRECT_SHAPE":
            return 
                ...state,
                ...action // will add `type` and `payload` to returned object
            
        default:
            return state;
    

在这个简化的版本中,我试图展示正在发生的事情:

在第一个case 中,返回的对象将是正确的,而且我没有收到来自编译器的警告。 在第二个case 中,编译器正确警告我otherprop 不是Shape 接口的成员。 最后一个实际上是错误发生的地方。传播action 对象实际上会返回一个带有额外payloadtype 属性的对象,并且不会覆盖value

我想在这里了解为什么 typescript 在第三个case 条件下没有警告我,我正在构建一个形状不是State 的对象,例如在第二个case 中。

这是扩展语法的限制还是我在这里忽略了什么?

Typescript playground link

【问题讨论】:

似乎只要最终对象包含value 属性(以符合State 接口),那么 anything else 就被接受了毫无疑问。即使手动添加任何其他属性正确地报告错误。很奇怪。 【参考方案1】:

此行为是设计使然。你会在 GH 上找到几个关于此的问题(如 this 或 this)。官方推理可以找到here:

原因:新鲜度检查是为了发现选项包之类的问题 - 这听起来更像是精确类型的潜在案例

【讨论】:

以上是关于扩展语法是不是会创建误报类型安全返回的对象?的主要内容,如果未能解决你的问题,请参考以下文章

org.jooq.Query.getBindValues() 返回的 List<Object> 是不是包含类型安全的对象 - 对于每个查询参数?

Typescript 类型推断、扩展语法和多类型返回

为什么赋值操作符函数的参数为const引用,返回值为引用

Swift5.4 中可选的误报

PHP 是不是具有在给定有效内容类型的情况下返回正确文件扩展名的函数?

返回列表而不是IQueryable