【问题标题】:TS2339: Property 'X' does not exist on type 'Y' (Non-indexable type union case)TS2339:类型“Y”上不存在属性“X”(非可索引类型联合案例)
【发布时间】:2020-03-26 16:12:59
【问题描述】:

与类似问题的区别

error TS2339: Property 'x' does not exist on type 'Y' 中,主题是indexable type。这不是,所以很可能需要其他解决方案。

问题

interface INumberPropertySpecification__CommonParameters {
  readonly type: PROPERTIES_TYPES.NUMBER; // enum
  readonly numberType: NUMBER_TYPES; // enum
}

export type NumberPropertySpecification =
      INumberPropertySpecification__Required |
      INumberPropertySpecification__HasDefault |
      INumberPropertySpecification__Optional;

在上面的代码中,NumberPropertySpecification 是以下情况的并集:

  1. 该属性是必需的。在这种情况下,图书馆用户必须理解它,所以我让他明确指定required: true
interface INumberPropertySpecification__Required extends INumberPropertySpecification__CommonParameters {
    readonly required: true;
    readonly invalidValueSubstitution?: number;
}

// Example:

const requiredNumberPropertySpecification: INumberPropertySpecification__Required = {
  type: PROPERTIES_TYPES.NUMBER,
  numberType: NUMBER_TYPES.ANY_REAL_NUMBER,
  required: true // user MUST comprehend it, so I make him to explicitly specify it
}
  1. 该属性有默认值;这意味着它不是必需的。我不想让用户指定required: false,因为这很明显。
interface INumberPropertySpecification__HasDefault extends INumberPropertySpecification__CommonParameters {
    readonly defaultValue: number;
}

// Example
const requiredNumberPropertySpecification: INumberPropertySpecification__HasDefault = {
  type: PROPERTIES_TYPES.NUMBER,
  numberType: NUMBER_TYPES.ANY_REAL_NUMBER,
  default: 1
}
  1. 该属性是可选的。在这种情况下,用户必须理解它,所以我让他明确指定required: false
interface INumberPropertySpecification__Optional extends INumberPropertySpecification__CommonParameters {
    readonly required: false;
}

// Example:

const requiredNumberPropertySpecification: INumberPropertySpecification__Optional = {
  type: PROPERTIES_TYPES.NUMBER,
  numberType: NUMBER_TYPES.ANY_REAL_NUMBER,
  required: false // user MUST comprehend it, so I make him to explicitly specify it
}

错误

我们无法检查targetPropertySpecification.required === true。在这种情况下,TypeScript 类型检查算法就大材小用了,因为当 targetPropertySpecification.required 未定义时,不会发生 JavaScript 错误(即使只是 if(targetPropertySpecification.required),但使用 "@typescript-eslint/strict-boolean-expressions": 的人不能写这样的)。

defaultValueisUndefined)相同的歌曲:

【问题讨论】:

    标签: typescript typescript-typings


    【解决方案1】:

    您的代码与discriminated union 非常相似,但您为此使用了required

    JavaScript(和 TypeScript)区分具有 undefined 值的现有属性和不存在的属性。因此,为了使您的代码正常工作,您应该将可选属性 requireddefaultValue 添加到所有接口。

    interface INumberPropertySpecification__Required extends INumberPropertySpecification__CommonParameters {
      readonly required: true;
      readonly invalidValueSubstitution?: number;
      readonly defaultValue?: undefined;
    }
    

    defaultValue 的类型明确为undefined,并且设置为可选。

    其他两个接口也应该做类似的修改。

    interface INumberPropertySpecification__HasDefault extends INumberPropertySpecification__CommonParameters {
      readonly defaultValue: number;
      readonly required?: undefined;
    }
    
    interface INumberPropertySpecification__Optional extends INumberPropertySpecification__CommonParameters {
      readonly required: false;
      readonly defaultValue?: undefined;
    }
    

    现在你仍然可以做

    const targetPropertySepcification: NumberPropertySpecification = {
      required: true,
      type: PROPERTIES_TYPES.NUMBER,
      numberType: NUMBER_TYPES.T1
    }
    

    您无需为defaultValue 提供值。它设置为undefined

    以下代码将起作用

    function f1(targetPropertySepcification: NumberPropertySpecification) {
      if (targetPropertySepcification.required === true) {
        // targetPropertySepcification is of type INumberPropertySpecification__Required
        const n: number | undefined = targetPropertySepcification.invalidValueSubstitution;
      } else if (targetPropertySepcification.required === false) {
        // targetPropertySepcification is of type INumberPropertySpecification__Optional
      } else if (targetPropertySepcification.required === undefined) {
        // targetPropertySepcification is of type INumberPropertySpecification__HasDefault
        const n: number = targetPropertySepcification.defaultValue;
      }
    
      if (targetPropertySepcification.defaultValue === undefined) {
        // Here targetPropertySepcification is of type INumberPropertySpecification__Required | INumberPropertySpecification__Optional 
        //  and required property is of type true | false, or simply boolean
        const rt: boolean = targetPropertySepcification.required
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2016-11-14
      • 1970-01-01
      • 2019-01-11
      • 2021-12-15
      • 2016-03-14
      • 2017-02-25
      相关资源
      最近更新 更多