【问题标题】:Typescript interface type with optional keys of different types and strictNullChecksTypescript 接口类型,带有不同类型的可选键和 strictNullChecks
【发布时间】:2017-02-15 16:18:42
【问题描述】:

我正在尝试在 typescript 中创建以下界面:

type MoveSpeed = "min" | "road" | "full";

interface Interval {
  min?: number,
  max?: number
}

interface CreepPlan {
  [partName: string] : Interval;
  move?:    MoveSpeed;
}

但是,此语法无效。编译器说Property 'move' of type '"min" | "road" | "full" | undefined' is not assignable to string index type 'Interval'.

我正在使用编译器选项 strictNullChecks:true,这就是为什么 undefined 隐式包含在 move? 键中。

但是,这个语法是有效的:

type MoveSpeed = "min" | "road" | "full";

interface Interval {
  min?: number,
  max?: number
}

interface CreepPlan {
  [partName: string] : Interval;
  move:    MoveSpeed;            // 'move' is required
}

我想表达“CreepPlan 由 string:Interval 对组成的想法,除了可选的 'move' 键是一个 string:MoveSpeed 对。”可以用打字稿来表达吗?

【问题讨论】:

  • 我认为问题可能在于您在哪里(以及如何)使用该代码,而不是代码本身,因为您的示例编译时没有错误
  • @ssube 抱歉,我正在使用 strictNullChecks 设置为 true。我会澄清的。

标签: typescript


【解决方案1】:

如打字稿docs 中所述,如果您使用可索引属性,则所有其他属性的所有返回类型都应可分配给索引返回类型的返回类型。 那是因为foo['bar']foo.bar 是一样的。

那么为什么会这样呢?

interface CreepPlan {
    [partName: string]: Interval;
    move: MoveSpeed;
}

因为任何MoveSpeed 都是有效的Interval 值(它是一个未定义min/max 的区间。

为什么这不起作用?

interface CreepPlan {
     [partName: string]: Interval;
     move?: MoveSpeed;
 }

move? 具有类型 MoveSpeed 加上 undefined 类型。如果 is 具有未定义的值,则它不能分配给 Interval,因此编译器会正确显示错误。

你怎么能解决这个问题?只需让索引器将undefined 作为有效值:

interface CreepPlan {
    [partName: string]: Interval | undefined;
    move?: MoveSpeed;
}

【讨论】:

    【解决方案2】:

    您在写的时候声明CreepPlan 上的所有属性都有Interval-type 值:

    interface CreepPlan {
      [partName: string] : Interval;
    }
    

    即,CreepPlan 的所有字符串索引可访问属性都将是 Interval。这也适用于move,因为foo['move']foo.move 相同。

    然而,看看Interval,它没有必要的结构:

    interface Interval {
      min?: number,
      max?: number
    }
    

    该合同中没有必填字段,但它确实需要一个对象。它会很乐意接受一个空对象,但它需要一些可以具有minmax属性的对象。

    另一方面,您的MoveSpeed 类型允许undefined

    属性“移动”类型为“最小”| “路” | “满” | undefined' 不能分配给字符串索引类型 'Interval'。

    因此,Interval 必须是一个没有必需属性的对象(string 可以轻松满足)但不允许 undefined,而 MoveSpeed确实允许。

    你的类型是不相交的,但直到你解决它们一两次才明显。

    【讨论】:

    • 感谢您的回答。这也是我的直觉,但我不明白为什么我的问题中的第二个示例(move 作为必需成员)是有效的。也许是打字稿编译器的一些怪癖。
    • @Oliver 我想我知道。编辑它,只需几秒钟。
    猜你喜欢
    • 2020-03-11
    • 1970-01-01
    • 2022-01-27
    • 2020-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-15
    相关资源
    最近更新 更多