按类型迭代TypeScript接口的属性

z2acfund  于 6个月前  发布在  TypeScript
关注(0)|答案(1)|浏览(85)

我有一个 typescript 的界面,

interface StatusTO {
  name: string,
  identifier: string
}

字符串
另一个是这样用的

export interface RowObject {
  partNumber: string,
  version: string,
  versionCount: number,
  status: StatusTO,
}


然后,我有一个通用的搜索功能如下:

public isSearchedFor<T extends RowObject>(row: T, key: keyof T, searchTerm: string): boolean {
  let element = row[key];
  let stringValue: string | undefined = undefined;
  switch (key) {
    case 'partNumber':
    case 'version':
      stringValue = (element as string);
      break;
    case 'versionCount':
      stringValue = (element as number).toString();
      break;
    case 'status':
      stringValue = (element as StatusTO).name;
  }
  return stringValue?.includes(searchTerm) ?? false;
}


我把它叫做

row = {
  partNumber: 'You have to FindMe',
  version: '123',
  versionCount: 2,
  status: {
    name: '200',
    identifier: 'OK'
  }
}


通过isSearchedFor(row, 'partNumber', 'FindMe');返回true
在有switch语句的地方,我想覆盖RowObject的所有可能的属性类型,如'string','number'和'StatusTO',而不是让它更容易扩展,每当一个相同类型的新属性将被添加。切换接口RowObject的所有属性的解决方案不是最好的。我如何通过它们的类型自动处理所有属性呢?当只有简单的类型,如字符串和数字,我可以切换(typeof元素)。然而,我有一个复杂的对象类型,如StatusTO包括在内,所以我怎么能解决这个问题。最好的解决方案是类型安全,也许与类型后卫?

5t7ly7z5

5t7ly7z51#

要根据类型处理RowObject的所有属性,可以使用类型保护和条件语句。下面是自动处理所有属性类型的isSearchedFor函数:

type Primitive = string | number | boolean;

function isPrimitive(value: any): value is Primitive {
  return typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean';
}

function isStatusTO(value: any): value is StatusTO {
  return typeof value === 'object' && 'name' in value && 'identifier' in value;
}

function getPropertyAsString(value: any): string {
  if (isPrimitive(value)) {
    return value.toString();
  } else if (isStatusTO(value)) {
    return value.name;
  }

  // Add more type checks and conversions here if needed

  return '';
}

export function isSearchedFor<T extends RowObject>(row: T, key: keyof T, searchTerm: string): boolean {
  const element = row[key];
  const stringValue = getPropertyAsString(element);
  return stringValue.includes(searchTerm);
}

字符串
在这个版本中,添加了一个isPrimitive类型保护来检查一个值是否是原始类型(stringnumberboolean)。还添加了一个isStatusTO类型保护来检查一个值是否是StatusTO类型。
getPropertyAsString函数处理将不同的属性类型转换为字符串。目前,它处理基本类型和StatusTO。如果需要,可以向此函数添加更多类型检查和转换。
isSearchedFor函数中,getPropertyAsString函数用于获取属性值的字符串表示。然后检查返回的字符串是否包含搜索项。
当新的属性类型被添加到RowObject时,这种方法允许简单的扩展。人们可以简单地向getPropertyAsString函数添加更多的类型保护和转换来处理新类型。
也可以使用switch语句:

function getPropertyAsString(value: any): string {
  switch (typeof value) {
    case 'string':
    case 'number':
    case 'boolean':
      return value.toString();
    case 'object':
      if (Array.isArray(value)) {
        // Handle array types
        return value.map((item: any) => getPropertyAsString(item)).join(', ');
      } else if ('name' in value && 'identifier' in value) {
        // Handle StatusTO type
        return (value as StatusTO).name;
      }
  }

  return '';
}


这里甚至还添加了数组的递归处理,因此string[]甚至StatusTO[]属性都可以很好地处理。
当有一个像这样的字符串枚举时:

enum YesNoIcon {
  UNDEFINED = 'undefined',
  YES = 'yes',
  NO = 'no'
}


然后你可以导出一个函数,

export const isYesNoIcon = (element: any): element is YesNoIcon =>
  !!element
  && Object.values(YesNoIcon).filter(value => isNaN(Number(value))).includes(element);


并在切换前使用它:

// must be before (typeof value === 'string') as it is a string enum
if (isYesNoIcon(value))
{
  return value;
}

相关问题