在打字稿中访问泛型类型的属性?

Ole*_*Ole 2 javascript typescript angular

将泛型类型转换为某些实体(例如 Product、Post、Todo、Customer 等)的任何作品(类型 E 将是打字稿类型、类或接口):

function test<E>(o:E):string {
  return (o as any)['property']
}
Run Code Online (Sandbox Code Playgroud)

只是想看看投射到any 通常是否应该如何处理?

要求提供完整的背景信息。这是正在实现的整个功能:

/**
 * 
 * @param entities The entities to search
 * @param exclude Keys to exclude from each entity
 * 
 * @return E[] Array of entities with properties containing the search term.
 */
export function search<E extends WithProperty>(query:string='', entities:E[], exclude:string[]=[]) {
  const { isArray } = Array

  query = query.toLowerCase();

  let keys:string[] = []
  if (entities.length > 0) {
    keys = excludeKeys(entities[0], exclude)
  }

  return entities.filter(function (e:E) {
    return keys.some((key)=>{
      const value = (e as any)[key];
      if (isArray(value)) {
        return value.some(v => {
          return new String(v).toLowerCase().includes(query);
        });
      }
      else if (!isArray(value)) {
        return new String(value).toLowerCase().includes(query);
      }
    })
  });
}

Run Code Online (Sandbox Code Playgroud)
/**
 * The method can be used to exclude keys from an instance
 * of type `E`.  
 * 
 * We can use this to exclude values when searching an object.
 * 
 * @param entity An instance of type E
 * @param eclude  The keys to exclude
 * 
 */
export function excludeKeys<E>(entity: E, exclude: string[]) {
  const keys: string[] = Object.keys(entity);
  return keys.filter((key) => {
    return exclude.indexOf(key) < 0;
  });
}


Run Code Online (Sandbox Code Playgroud)

Eld*_*dar 6

如果您知道类型约束有一个名为 property 的属性,您可以定义一个定义该属性的接口,然后使用告诉 E 扩展它的约束。然后您无需强制转换即可访问该属性。

interface WithProperty{
  property:string;
}

function test<E extends WithProperty>(o:E):string {
  return o.property;  // or o["property"] is valid access.
}
Run Code Online (Sandbox Code Playgroud)

操场

编辑:自从您更新了示例以来。还有另一种方法可以做到这一点,那就是使用关键字keyof。使用这个也不需要了解属性。我已经修改了您的示例,如下所示:

export function search<E>(query:string='', entities:E[], exclude:string[]=[]) {
  const { isArray } = Array
  type EKey = keyof E;
  query = query.toLowerCase();

  let keys : EKey[] = []
  if (entities.length > 0) {
    keys = excludeKeys<E>(entities[0], exclude)
  }

  return entities.filter(function (e:E) {
    return keys.some((key =>{
      const value = e[key];
      if (isArray(value)) {
        return value.some(v => {
          return v.toLowerCase().includes(search);
        });
      }
      else if (!isArray(value)) {
        return new String(value).toLowerCase().includes(query);
      }
    })
  });
 }
Run Code Online (Sandbox Code Playgroud)

由于这个漫长的讨论,对于排除键部分的代码转换变得不可避免。

export function excludeKeys<E>(entity: E, exclude: string[]) {
 const keys: string[] = Object.keys(entity);
  return <(keyof E)[]>keys.filter((key) => {
    return exclude.indexOf(key) < 0;
   });
}
Run Code Online (Sandbox Code Playgroud)

操场