简体   繁体   中英

typescript: implementing an interface using specific objects as a function arg

It's easier to explain this by looking at the actual code:

interface FooInterface {
  bar: (flags: { [key: string]: string }) => void;
}

export class Foo implements FooInterface {
  bar(flags: { myFlag: string }) {}
}

I want anyone who implements FooInterface.bar to pass an object. I don't care about the keys.

However, when I implemented it in Foo class and I named the key as myFlag I got an error that this key doesn't exist in the interface. See the complete error below.

How do I tell Typescript to ignore the keys in the implemented classes?

The error I got:

src/extensions/test/test.provider.ts:24:3 - error TS2416: Property 'bar' in type 'Foo' is not assignable to the same property in base type 'FooInterface'.
  Type '(flags: { myFlag: string; }) => void' is not assignable to type '(flags: { [key: string]: string; }) => void'.
    Types of parameters 'flags' and 'flags' are incompatible.
      Property 'myFlag' is missing in type '{ [key: string]: string; }' but required in type '{ myFlag: string; }'.

24   bar(flags: { myFlag: string }) {}
     ~~~

Using generic typings, you can force the flags to be an object with string values, then specify the type in the class implementation:

interface FooInterface<T extends { [key: string]: string }> {
  bar: (flags: T) => void;
}

type BarFlags = { myFlag: string };

export class Foo implements FooInterface<BarFlags> {
  bar(flags: BarFlags) {}
}

Playground Link

The problem is that you are saying myFlag must be a string , but the type { [key: string]: string } does not guarantee that the myflag key actually exists. So it cannot satisfy the string type.

If you make the myFlag key optional it works, you then just have to check it for existence.

interface FooInterface {
  bar: (flags: { [key: string]: string }) => void;
}

export class Foo implements FooInterface {
  bar(flags: { myFlag?: string }) {
    if (flags.myFlag) {
      console.log(flags.myFlag) // logs a string
    }
  }
}

Playground


If you want to enforce that myFlag is provided when you call bar is the Foo class, then @leonardfactory's answer is what you need.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM