首页 > 解决方案 > 不能在接口内使用自定义类型

问题描述

我似乎无法理解为什么我不能在界面中使用自定义类型。

我有以下定义:

type Operation = 'update'|'remove'|'add'
interface Rule {
  op: Operation
  path:string
  value?:any
}

function applyDiff<Output>(rules: Rule[], obj: object): Output;

但我Type 'string' is not assignable to type 'Operation'在这个失败的测试中收到一个错误:

const obj = {a: {b:1, c:2}}
const rules = [
  {op: 'update', path: 'a.c', value:10},
] 
const result = applyDiff(rules, obj)

但这段代码工作得很好:

function fn(x: number, y: 'add'|'remove'|'update'){
  return x > 1 && y === 'add'
  
}
const result = fn(1, 'remove')

我在这里缺少什么?我将不胜感激有关此事的任何有用指导。谢谢你。

标签: typescript

解决方案


首先,简单的解决方案:

const rules: Rule[] = [
        // ^------^
  {op: 'update', path: 'a.c', value:10},
] 

但为什么一开始就不起作用呢?因为推断的类型rulesis {op: string; path: string; value: number}[],并且有很多strings 不是Operation联合中的任何值。对象和数组是可变的,因此没有什么可以阻止op在定义rules和传递它到applyDiff.

这也提出了一些其他的解决方案:

  1. 将数组直接传递给函数:

    const result = applyDiff([
      {op: 'update', path: 'a.c', value:10},
    ], obj);
    

    在定义数组和将其传递给 之间,值无法更改,因此推断出applyDiff更窄的类型。{op: 'update'; path: 'a.c'; value: 10}[]

  2. 使用const断言显式缩小规则的类型:

    const rules = [
      {op: 'update', path: 'a.c', value:10} as const,
                                        // ^-------^
    ];
    

    这告诉编译器您认为该对象是不可变的,这也导致它推断出更窄的类型rules。您可以改为显式缩小 的类型op

    const rules = [
      {op: 'update' as const, path: 'a.c', value:10},
                // ^-------^
    ];
    

    具有类似的效果。


推荐阅读