typescript 如何删除不符合typestrip接口的额外对象属性?

67up9zun  于 2023-02-25  发布在  TypeScript
关注(0)|答案(3)|浏览(242)

我有这个代码,没有显示错误,但显然有一个错误:

import axios from 'axios'
interface Character {
    name: string,
    birthday: string 
}

const url = 'https://breakingbadapi.com/api/characters'
async function char(): Promise<Character[]> { 
    return await axios.get(url).then(res => res.data)
}

(async function() {
    
let chacater: Character[] = await char(); 
console.log(character[0]) 
})()

每个角色对象都有很多属性,我只想要名字和生日,所以在Character接口中指定了
但是当我控制台日志character[0]时,我得到的不仅仅是名字和生日。
其他的一切都应该被过滤掉吗,还是我应该犯某种错误?

zyfwsgd6

zyfwsgd61#

也许你可以检查类转换器。但是,你需要使用类定义而不是接口。顺便说一句,你也可以利用class-validation,它可以保证你得到的数据是正确的和预期的。

46qrfjad

46qrfjad2#

当你在TS中定义一个接口时,你基本上告诉TS对象将只包含那些键和它们对应的类型。当你定义一个返回该类型的函数时,这取决于你作为开发人员,以确保它确实如此。
你可以像下面这样写 char 函数来过滤掉所有其他的键,并确保数组中的每个 character 都有这些键:

async function char(): Promise<Character[]> {
  return await axios.get(url).then((res) =>
    res.data.map(({ name, birthday }) => ({
      name: typeof name === "string" ? name : "",
      birthday: typeof birthday === "string" ? birthday : ""
    }))
  );
}
ef1yzkbh

ef1yzkbh3#

@Tobias S已经正确地指出,我最初的答案实际上并没有做我认为它做的事情--在我花了15分钟研究代码之后,我同意他的结论,即这实际上不可能用开箱即用的TypeScript。
我认为使用https://github.com/kimamula/ts-transformer-keys是可能的--这是一个自定义转换器,允许您在运行时获取类型的键。
代码如下所示:

export function filterProperties(obj:any, allowedKeys:string[]) {
  for (const prop in obj) {
    if (!allowedKeys.includes(prop as InnerComponentPropsKeys)) {
      delete obj[prop];
    }
  }
  return obj;
}

您需要向它传递允许的键,使用keys<T>()方法从自定义转换器中检索。所以类似于这个React示例,其中父组件props扩展子组件的props,我希望传播props而不是重复它们。例如:

interface OuterComponentProps extends InnerComponentProps {
  somePropThatIsUsedInTheOuterComponent: string;
}

const OuterComponent = (props: OuterComponentProps): JSX.Element => {
  const innerComponentProps = filterProperties(props, keys<InnerComponentProps>()) as InnerComponentProps;
  return <div>
    <div>
      {props.somePropThatIsUsedInTheOuterComponent}
    </ div>
    <InnerComponent {...innerComponentProps } />
  </ div>;
};

理想情况下,您可以将整个过程 Package 在一个通用的helper方法中,如下所示:

export function filterProperties<T>(originalObject: T): T {
  const filteredObject = {} as T;
  const allowedProperties = keys<T>();
  allowedProperties.forEach((propertyKey) => {
    filteredObject[propertyKey] = originalObject[propertyKey];
  });
  return filteredObject;
}

但这并不起作用,因为不幸的是,这个自定义转换器不适用于泛型/动态类型,所以不容易像我最初想的那样将其 Package 在一个泛型helper方法中(参见https://github.com/kimamula/ts-transformer-keys#note)。
另一个大的缺点是它涉及到使用一个定制的转换器,这也不是微不足道的(参见https://github.com/kimamula/ts-transformer-keys#how-to-use-the-custom-transformer)

相关问题