我有一个名为Design的TypeScript类,它包含一个名为checkFetched的方法.此方法被设计为基于称为Filename的参数化类型来判断类实例中是否存在类型DesignData的属性.下面是代码的简化版本:

type Filename = 'original' | 'result'
type DesignData = {
  id: string
  // ...
}

export class Design {
  original?: DesignData
  result?: DesignData

  checkFetched(target: Filename): this is { [K in typeof target]: DesignData } {
    return !!this[target]
  }

  private async loadDesign(fileName: Filename) {
    if (!this.checkFetched(fileName)) return
    const shouldNotHaveUndefined = this[fileName]
    const shouldHaveUndefined1 = this.original
    const shouldHaveUndefined2 = this.result
  }

  private async loadDesign2() {
    if (!this.checkFetched('original')) return
    const shouldNotHaveUndefined = this.original
    const shouldHaveUndefined = this.result
  }
}

checkFetched方法返回一个布尔值,指示指定的属性是否存在.但是,我想优化这个方法的返回类型,如果判断通过,TypeScript应该推断相应的属性不是undefined,而其他属性仍然可以是undefined.

例如,在loadDesign2方法中调用checkFetched('original')后,TypeScript应该理解shouldNotHaveUndefined不是undefined,但shouldHaveUndefined1shouldHaveUndefined2可以是undefined.现在,shouldHaveUndefined将被视为不是undefined.

考虑到我的try ,我希望通过细化返回类型,TypeScript在调用checkFetched后能正确推断出属性的存在.

我正在寻求社区的见解,以确定这种方法是否可以修改以满足我的需求,或者这种要求是否本质上不可能在TypeScript中实现.

请使用此TypeScript Playground链接探索和分享您的见解:TypeScript Playground

推荐答案

您当前的checkFetched结果类型太宽,它说名称在Filename union(即originalresult)中的any属性不是undefined,但您希望它告诉TypeScript target中具有specific名称的属性不是undefined.要做到这一点,您将函数设为泛型:

checkFetched<Target extends Filename>(target: Target): this is { [K in Target]: DesignData } {
    return !!this[target];
}

(100 could also be written 101, which by using an idiom may be a bit clearer — or not, it's a style choice.)

支票的工作方式我想你的意思是:

private async loadDesign<Target extends Filename>(fileName: Target) {
    if (!this.checkFetched(fileName)) return;
    const shouldNotHaveUndefined = this[fileName];
    //    ^? const shouldNotHaveUndefined: (this & { [K in Target]: DesignData; })[Target]
    console.log(shouldNotHaveUndefined.id); // (Just to show that the above really means it's not `undefined`)
    // No error −−−−−−−−−−−−−−−−−−−−−−−^
    const shouldHaveUndefined1 = this.original;
    //    ^? const shouldHaveUndefined1: DesignData | undefined
    const shouldHaveUndefined2 = this.result;
    //    ^? const shouldHaveUndefined2: DesignData | undefined
}

private async loadDesign2() {
    if (!this.checkFetched("original")) return;
    const shouldNotHaveUndefined = this.original;
    //    ^? const shouldNotHaveUndefined: DesignData
    const shouldHaveUndefined = this.result;
    //    ^? const shouldHaveUndefined: DesignData | undefined
}

Updated playground

Typescript相关问答推荐

如何传递基于TypScript中可变类型的类型?

部分类型化非 struct 化对象参数

为什么ESLint会抱怨函数调用返回的隐式`any`?

通过泛型函数本身推断受约束的泛型参数的类型脚本问题

TypeScrip:从对象中提取和处理特定类型的键

有没有办法防止类型交集绕过联合类型限制?

跟踪深度路径时按条件提取嵌套类型

对于VUE3,错误XX不存在于从不存在的类型上意味着什么?

在类型脚本中创建显式不安全的私有类成员访问函数

如何在Reaction Native中关注屏幕时正确更新状态变量?

基于属性值的条件类型

如何处理可能为空的变量...我知道这不是Null?

在Vite中将SVG导入为ReactComponent-不明确的间接导出:ReactComponent

通过辅助函数获取嵌套属性时保留类型

显式推断对象为只读

Next 13 + React 18 createContext 类型的构建问题

具有枚举泛型类型的 Typescript 对象数组

如何在 TypeScript 类型定义中简化定义长联合类型

TS2532:对象可能未定义

如何在 ngFor 循环中以Angular 正确动态渲染组件