Typescript v4.3.5:类型防护装置问题- S2339:属性“a”在类型“never”上不存在

oxcyiej7  于 2023-04-22  发布在  TypeScript
关注(0)|答案(1)|浏览(117)

有一个检查http请求类型的守卫。它作为一个库工作,并作为来自另一个库的嵌套代码停止。

export function isTenantRequest(object: unknown): object is TenantRequest {
  return (
    !!object && // #a Check that it is not undefined nor null. -> not null
    object instanceof Object && // #b So it can contain properties. -> Object
    'tenant' in object && // #c The property exists that I am going to check -> { tenant: any } !!! maybe never
    object.tenant instanceof TenantDO && // #d Checks the instance -> -> { tenant: any }
    validateSync(object.tenant).length === 0 // #f Validates by a validator.
  );
}

在第#d行,我收到一个 typescript 错误。

error TS2339: Property 'tenant' does not exist on type 'never'.
23(#f)     validateSync(object.tenant).length === 0

我猜in操作符不能在简单的Object上工作,因为它不能有额外的属性,这就是为什么它返回never type,并且在下一行失败。我已经改变了下一个可行的变体,但我不喜欢,因为as操作符。

export function isTenantRequest(object: unknown): object is TenantRequest {
  return (
    (object as TenantRequest).tenant instanceof TenantDO &&
    validateSync((object as TenantRequest).tenant).length === 0
  );
}

有人建议

typeof x === 'object'

但这并没有帮助。
请给我一些建议,让它变得更好。

50few1ms

50few1ms1#

Typescript4.3在使用in操作符进行缩小方面不够智能,这在Typescript4.9中得到了改变
所以我认为在没有as类型Assert的4.3版本中这是不可能的,但是你至少可以通过聪明地选择在哪里做Assert来避免任何运行时崩溃。
我可能会这样重构:

class TenantDO { constructor(public tenantName: string) {} }
declare function validateSync(tenant: TenantDO): unknown[]

export function isTenantRequest(value: unknown) {
  if (!value || typeof value !== 'object') return false
  const valueAsObject = value as Record<string, unknown>
  
  return (
    'tenant' in valueAsObject &&
    valueAsObject.tenant instanceof TenantDO &&
    validateSync(valueAsObject.tenant).length === 0
  );
}

现在为了得到value as Record<string, unknown>行,value * 必须 * 是一个能够拥有属性的对象。所以你Assert它是Record<string, unknown>,它允许你访问任何属性,但不保证你从该属性中得到什么。
然后,现有代码的其余部分按原样工作,以验证该属性。
参见Typescript v4.3.5 Playground
如果你想删除那个as,那么你很可能需要升级到一个更新的Typescript版本。

相关问题