【问题标题】:Typescript property type guards on unknownTypescript 属性类型保护未知
【发布时间】:2021-12-10 18:53:17
【问题描述】:

我正在尝试输入保护未知类型

const foo  = (obj: unknown) => {
    if (typeof obj === 'object' && obj) {
        if ('foo' in obj && typeof obj.foo === 'string') {
            return obj.foo;
        }
    }
};

But I'm getting

“对象”类型上不存在属性“foo”。

我也试过is表达式不起作用:

const foo  = (obj: unknown): obj is { foo: 'string' } => {
    if (typeof obj === 'object' && obj) {
        if ('foo' in obj && typeof obj.foo === 'string') {
            return obj;
        }
    }
    throw new Error();
};

【问题讨论】:

  • 在检查foo之前尝试将obj转换为any
  • @RickyMo 你的意思是(obj: any) => {... ?
  • 您使用unknown 是否有特定原因? any 会起作用,但你特别提到了unknown 所以......
  • 我正在使用 gts 预设,在使用 any 时会向我发出警告。而且我更喜欢输入检查代码,因为它是用户编写的代码

标签: typescript typeguards


【解决方案1】:

请考虑使用这个助手:

const hasProperty = <Obj, Prop extends string>(obj: Obj, prop: Prop)
  : obj is Obj & Record<Prop, unknown> =>
  Object.prototype.hasOwnProperty.call(obj, prop);

在你的情况下。 in 运算符按预期工作,主要与工会合作。请参阅hereherehere

工作解决方案:

const hasProperty = <Obj, Prop extends string>(obj: Obj, prop: Prop)
  : obj is Obj & Record<Prop, unknown> =>
  Object.prototype.hasOwnProperty.call(obj, prop);

const foo = (obj: unknown) => {
  if (typeof obj === 'object' && obj) {
    if (hasProperty(obj, 'foo') && typeof obj.foo === 'string') {
      return obj.foo;
    }
  }
};

Playground

但是,如果obj 无效,您想抛出错误,您可以使用assert function

const hasProperty = <Obj, Prop extends string>(obj: Obj, prop: Prop)
  : obj is Obj & Record<Prop, unknown> =>
  Object.prototype.hasOwnProperty.call(obj, prop);

function foo(obj: unknown): asserts obj is { foo: string } {
  const isValid =
    typeof obj === 'object' &&
    obj &&
    hasProperty(obj, 'foo') &&
    typeof obj.foo === 'string';

  if (!isValid) {
    throw new Error();
  }

};

declare var obj: unknown;

foo(obj);

obj.foo // ok

Playground

【讨论】:

  • 感谢您的努力 :) 我将使用解决方案 #1,它更简单,但这个不需要“额外帮助”:)
【解决方案2】:

你将不得不在这里给 TypeScript 一点帮助:

type fooObj = object & { foo: unknown };
const foo = (obj: unknown) => {
    if (typeof obj === 'object' && obj) {
        if ('foo' in obj && typeof (obj as fooObj).foo === 'string') {
            return (obj as fooObj).foo;
        }
    }
};

【讨论】:

    猜你喜欢
    • 2020-02-01
    • 1970-01-01
    • 2021-05-17
    • 2020-12-16
    • 2020-05-07
    • 1970-01-01
    • 2021-01-22
    • 2019-01-04
    • 1970-01-01
    相关资源
    最近更新 更多