我如何确定一个对象x是否具有定义的属性y,而不管x.y的值是多少?

我正在使用

if (typeof(x.y) !== 'undefined')

但这似乎有点笨拙。有没有更好的办法?


当前回答

包括

Object.keys(x).includes('y');

array .prototype.includes()方法确定数组在其条目中是否包含某个值,并根据需要返回true或false。

and

object. keys()返回一个字符串数组,表示给定对象的所有可枚举属性。

. hasownproperty()和ES6+ ?-option -chaining如:if (x?.y)是非常好的2020+选项。

其他回答

包括

Object.keys(x).includes('y');

array .prototype.includes()方法确定数组在其条目中是否包含某个值,并根据需要返回true或false。

and

object. keys()返回一个字符串数组,表示给定对象的所有可枚举属性。

. hasownproperty()和ES6+ ?-option -chaining如:if (x?.y)是非常好的2020+选项。

const data = [{"b":1,"c":100},{"a":1,"b":1,"c":150},{"a":1,"b":2,"c":100},{"a":2,"b":1,"c":13}]

const result = data.reduce((r, e)  => {
  r['a'] += (e['a'] ? e['a'] : 0)
    r['d'] += (e['b'] ? e['b'] : 0)
  r['c'] += (e['c'] ? e['c'] : 0)

  return r
}, {'a':0, 'd':0, 'c':0})

console.log(result)
`result` { a: 4, d: 5, c: 363 }

为什么不简单地:

if (typeof myObject.myProperty == "undefined") alert("myProperty is not defined!");

或者如果你想要一个特定的类型:

if (typeof myObject.myProperty != "string") alert("myProperty has wrong type or does not exist!");

你可以像这样修剪一下:

if ( x.y !== undefined ) ...

与此线程中的其他示例不同,此实现仅断言对象具有我们正在检查的属性。

const hasOwnProperty = <X extends {}, Y extends PropertyKey>(
  object: X,
  property: Y
): object is Record<Y, unknown> & X => {
  return object.hasOwnProperty(property);
};

下面是一个使用它来标识具有所需属性的分支的示例。

const hasOwnProperty = <X extends {}, Y extends PropertyKey>(
  object: X,
  property: Y
): object is Record<Y, unknown> & X => {
  return object.hasOwnProperty(property);
};

type PaidProjectFeeType = 'FIXED_PRICE' | 'RATE' | '%future added value';

const PAID_PROJECT_FEE_TYPE_LABELS: Record<
  'FIXED_PRICE' | 'RATE',
  string
> = {
  FIXED_PRICE: 'Fixed Price',
  RATE: 'Rate',
};

export const getPaidProjectFeeTypeLabel = (
  feeType: PaidProjectFeeType
): string => {
  if (hasOwnProperty(PAID_PROJECT_FEE_TYPE_LABELS, feeType)) {
    PAID_PROJECT_FEE_TYPE_LABELS[feeType];
  }

  throw new Error('test');
};

https://tsplay.dev/m0LBOm

令人恼火的是,现在PAID_PROJECT_FEE_TYPE_LABELS被假设为:

Record<PaidProjectFeeType, unknown> & Record<"FIXED_PRICE" | "RATE", string>

也就是说,你不能返回结果,因为X[Y]的可能值是未知的。当您需要断言对象具有所需的属性时,这很有用,但您将需要添加进一步的断言以确保结果是您想要的。

不过,有一个更好的办法。

我们需要两个工具:

export const keys = <T extends Record<string, unknown>>(
  object: T
): Array<keyof T> => {
  return Object.keys(object);
};

Keys为我们提供了对象属性名的类型化数组。

export const includes = <C extends M, M>(
  collection: readonly C[],
  member: M
): member is C => {
  return collection.includes(member as C);
};

Includes允许断言某个属性是只读数组的成员。你可以在这篇博客文章中阅读更多关于includes的内容。

export const keys = <T extends Record<string, unknown>>(
  object: T
): Array<keyof T> => {
  return Object.keys(object);
};

export const includes = <C extends M, M>(
  collection: readonly C[],
  member: M
): member is C => {
  return collection.includes(member as C);
};

type PaidProjectFeeType = 'FIXED_PRICE' | 'RATE' | '%future added value';

const PAID_PROJECT_FEE_TYPE_LABELS: Record<
  'FIXED_PRICE' | 'RATE',
  string
> = {
  FIXED_PRICE: 'Fixed Price',
  RATE: 'Rate',
};

export const getPaidProjectFeeTypeLabel = (
  feeType: PaidProjectFeeType
): string => {
  if (includes(keys(PAID_PROJECT_FEE_TYPE_LABELS), feeType)) {
    return PAID_PROJECT_FEE_TYPE_LABELS[feeType];
  }

  throw new Error('test');
};

https://tsplay.dev/N7gLDN

简而言之,这种方法允许我们将feeType值缩小到键中存在的值(PAID_PROJECT_FEE_TYPE_LABELS),然后允许我们访问属性值。

这种方法效果最好,但需要注意的是,从技术上讲,键的实现不是运行时安全的。在运行时返回的值与使用tsc推断的值不同的情况下(主要是理论性的)。