Why do I need to explicitly type my method arguments when implementing an interface?

For example:

interface Foo {
  someProperty: Number
  someMethod?: (str: string) => void
}

class Bar implements Foo {
  someProperty = 42
  someMethod (str) {
    console.log(this.someProperty)
  }
}

The str parameter to someMethod() is obviously a string. But the compiler complains:

test.tsx(8,15): error TS7006: Parameter 'str' implicitly has an 'any' type.

What am I doing wrong?

Edit: tsc --version reports version 2.8.3.

3 answers

  • answered 2018-05-16 04:43 basarat

    What am I doing wrong?

    Nothing. Its not supported in TypeScript as mentioned here.

    Fix

    Provide an explicit annotation in the class.

  • answered 2018-05-16 04:43 Ryan Cavanaugh

    The str parameter to someMethod() is obviously a string

    Not necessarily. You could have written a number of different signatures that satisfied the interface; for example

        someMethod (s: string | number) {
    

    or

        someMethod (s: any) {
    

    The implements clause is only a post hoc check on your class that makes sure your class successfully implemented the interface. It does not directly change the types of any declared properties or methods in your class.

    Because you'd have an implicit any if you didn't have the implements clause, you have an implicit any with it, because implements clauses don't affect the types of the class members.

  • answered 2018-05-16 04:55 artem

    Classes are not the only way to implement interfaces. You don't have to type method arguments explicitly if you use a function that creates and returns an object (sometimes called factory function) instead of a class:

    interface Foo {
      someProperty: number
      someMethod?: (str: string) => void
    }
    
    function createBar(): Foo {
        return {
            someProperty: 42,
            someMethod: (str) => {
                const n = str.length; // ok because parameter inferred as  str: string
            }
        }
    }