【问题标题】:Function parameter which implements an interface or an extension of the interface实现接口或接口扩展的函数参数
【发布时间】:2020-03-11 22:34:47
【问题描述】:

我有以下代码:

interface IFoo {
  foo: string;
}

interface IFooBar extends IFoo {
  bar: string;
}

const myFun = (fooOrFooBar: IFoo) => {
  console.log(fooOrFooBar.foo);
  console.log(fooOrFooBar.bar || "I do not have bar.");
}

const myFoo: IFoo = {
  foo: "Hello",
}

const myFooBar: IFooBar = {
  foo: "Hello",
  bar: "World!",
}

myFun(myFoo);
myFun(myFooBar);

这将允许我将实现IFooIFoo 扩展的对象传递给此函数,并以不同方式处理它们。但是,上面的代码不会编译为Property 'bar' does not exist on type 'IFoo'。有没有办法定义函数,使其接受实现IFoo 或扩展IFoo 的任何接口的参数?

【问题讨论】:

  • 如果你知道你要预先访问这个道具并且它们可以成为参数的一部分,为什么不相应地输入参数呢?例如const myFun = (fooOrFooBar: IFoo & Partial<IFooBar>) ...

标签: typescript interface


【解决方案1】:

如果你真的想接受任何像这样扩展 IFoo 的东西,你可以使用泛型:

const has = <K extends string>(
  key: K,
  x: object,
): x is { [key in K]: unknown } => (
  key in x
);

const myFun = <T extends IFoo>(fooOrFooBar: T) => {
  console.log(fooOrFooBar.foo);
  console.log(has('bar', fooOrFooBar) ? fooOrFooBar.bar : "I do not have bar.");
}

has 类型保护可用于安全访问您可能想要检查的任何属性。

但是,如果您已经预料到属性 bar 将成为对象的一部分,您也可以在没有泛型的类型签名中指定:

const myFun = (fooOrFooBar: IFoo | IFooBar) => {
  console.log(fooOrFooBar.foo);
  console.log('bar' in fooOrFooBar ? fooOrFooBar.bar : "I do not have bar.");
}

这仍然允许传递任何东西,它扩展了IFoo

const x = { foo: "fsd", x: 'sdf'}
myFun(x);

【讨论】:

    猜你喜欢
    • 2021-12-07
    • 1970-01-01
    • 2021-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-28
    相关资源
    最近更新 更多