reactjs 如何实现遵循T接口的通用对象检查 predicate ?

xlpyo6sf  于 2023-11-18  发布在  React
关注(0)|答案(1)|浏览(90)

我有下面的代码,代表两个接口和两个对象。然而,问题是如何创建一个通用的 predicate 函数,检查传递的对象是否符合上述接口。我尝试了 predicate 的其他实现,但它们显示了误报,因为在核心中,对象应该符合一个接口,而不是其他对象。

export const willObjectAdhereToInterface = <T>(item: any): item is T => {
  // Check for null and undefined only
  if (item === null || item === undefined) {
    return false;
  }
  // Check it is an object
  if (typeof item !== 'object') {
    return false;
  }

  // Get the expected keys of type T
  const expectedKeys: Array<keyof T> = Object.keys({} as T) as Array<keyof T>;

  // Check if all keys of T are present in the item
  return expectedKeys.every((key) => key in item);
};


interface A {
  a1: string;
  a2: string;
}

interface B {
  b1: string;
  b2: string;
  diffrence1: number;
  diffrence2: number;
}
const a: A = {
  a1: 'a1',
  a2: 'a2',
 
};

const b: B = {
  b1: 'b1',
  b2: 'b2',
  diffrence1: 0,
  diffrence2: 1,
};

if(willObjectAdhereToInterface<A>(a)){
// a is deffinatly of A interface 
}

if(willObjectAdhereToInterface<B>(b)){
// a is deffinatly of B interface 
}

if(willObjectAdhereToInterface<A>(b)){
console.log(b.a1) // must show an error.
}

字符串
至于我目前所做的是这2个通用函数,一个将检查对象,但它必须有所需的键来检查(不太好),另一个是检查使用第一个函数的set State action。

// T will represent the interface of the state
export const isGenericObject = <T>(object: any, requiredFields: string[] /* Pass the keys */): object is Partial<T> | T => {
  // Check for null and undefined only
  if (object === null || object === undefined) {
    return false;
  }
  // Check if object
  if (typeof object !== 'object') {
    return false;
  }

  // Retrieve keys from the item
  const keys = Object.keys(object);

  // Check if all required fields are present
  const hasAllRequiredFields = requiredFields.every((field) => keys.includes(field));

  return hasAllRequiredFields;
};

const isGenericSetState = <T>(object: any, setState: any): setState is Dispatch<SetStateAction<T>> => {
  // Check for null or undefined
  if (setState === null || setState === undefined) {
    return false;
  }

  // Check if setState has the expected type
  if (typeof setState !== 'function') {
    return false;
  }

  if (object !== undefined && isGenericObject(object, Object.keys(object))) {
    return true;
  }

  return false;
};

v7pvogib

v7pvogib1#

您混合了运行时(JavaScript)和编译时(TS类型)代码。运行时中不存在接口,因此您无法编写检查对象是否符合接口的代码。
如果你想检查运行时对象,那么最好的选择是你已经写过的isGenericObject,通过输入required fields属性进行了一点改进:

const isGenericObject = <T>(object: any, requiredFields: (keyof T)[]): object is Partial<T> | T => {

字符串
这一额外的论点是无法回避的。
您唯一可以做的其他事情是将接口转换为类,然后传递类本身,而不是必需的字段数组

const isGenericObject = <T>(object: any, ObjectClass: new () => T): object is Partial<T> | T => {
  const requiredKeys = Object.keys(new ObjectClass());
}


但是这需要你为每个类型创建一个构造函数,它将初始化所有必需的键,这比创建数组更糟糕。
有一种不同的方法你可以采取,但只有当你想在编译时的错误,并不会检查agains对象,你不知道他们是什么。这是使用extends来检查是否有效的东西:

const asSupertype = <TSuper, T extends TSuper>(obj: T) => obj as TSuper;

// ...

if(asSupertype<A, typeof b>(b)) { // compiler will show error on typeof b
}

相关问题