Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't infer param type of method assigned to computed property name using string enum value #20856

Closed
UselessPickles opened this issue Dec 22, 2017 · 3 comments
Labels
Fixed A PR has been merged for this issue

Comments

@UselessPickles
Copy link

UselessPickles commented Dec 22, 2017

TypeScript Version: 2.6.2

Code
With all strict options enabled...

// visitor interface for visiting possible values of a string literal type
type StringVisitor<S extends string, R> = {
    [P in S]: (value: P) => R;
};

enum Direction {
    LTR = "ltr",
    RTL = "rtl"
}

// "identity" visitor that just returns the visited value
const visitor: StringVisitor<Direction, Direction> = {
    // ERROR: Parameter 'value' implicitly has type 'any'.
    [Direction.LTR]: (value) => {
        return value
    },
    
    // no error - type of param properly inferred a type Direction.RTL
    ["rtl"]: (value) => {
        return value;
    }
}

Expected behavior:

No compiler error. The type of the param of the [Direction.LTR] method should be inferred as type Direction.LTR.

Actual behavior:
Compiler error because the type of the param of the [Direction.LTR] method is not inferred, so it is implicitly any.

It is interesting to me that I can use the enum values as computed property names to fulfill the requirements of the StringVisitor<Direction, Direction> type if I DON'T use parameters:

// No errors
const visitor: StringVisitor<Direction, Direction> = {
    [Direction.LTR]: () => {
        return Direction.LTR;
    },
    
    // no error
    [Direction.RTL]: () => {
        return Direction.RTL;
    }
}

Or if I explicitly provide the param type, everything lines up and compiles just fine:

// No errors
const visitor: StringVisitor<Direction, Direction> = {
    [Direction.LTR]: (value: Direction.LTR) => {
        return value;
    },
    
    [Direction.RTL]: (value: Direction.RTL) => {
        return value;
    }
}

The [Direction.LTR] and [Direction.RTL] property names seem to be understood as compile-time string literals for the purpose of matching up against the properties of the StringVisitor<Direction, Direction> type, and the distinct signatures of each property is known by the compiler for the purpose of checking that I provide a function of the correct type... so why can't the compiler infer the type of the param if I omit the param type?

NOTE: the same issue exists even if I declare the enum as a const enum.

@UselessPickles UselessPickles changed the title Can't infer param type of of method assigned to computed property name using string enum value Can't infer param type of method assigned to computed property name using string enum value Dec 22, 2017
@UselessPickles
Copy link
Author

UselessPickles commented Dec 22, 2017

NOTE: The mapped type StringVisitor is unnecessary complexity for the purpose of investigating this issue. I get the same results if I manually define a DirectionVisitor interface, like this:

enum Direction {
    LTR = "ltr",
    RTL = "rtl"
}

interface DirectionVisitor {
    ltr: (value: Direction.LTR) => Direction;
    rtl: (value: Direction.RTL) => Direction;
}

// "identity" visitor that just returns the visited value
const visitor: DirectionVisitor = {
    // ERROR: Parameter 'value' implicitly has type 'any'.
    [Direction.LTR]: (value) => {
        return value
    },
    
    // no error - type of param properly inferred a type Direction.RTL
    ["rtl"]: (value) => {
        return value;
    }
}

@DanielRosenwasser
Copy link
Member

DanielRosenwasser commented Dec 22, 2017

With #18317 and #15473, let us know what your experience is with our nightlies using npm install -g typescript@next. Seems to work for me.

image

@UselessPickles
Copy link
Author

UselessPickles commented Dec 22, 2017

typescript@next seems to work for me as well. Although, it was a bit confusing that a command-line compile succeeded, but VSCode still highlights the error. Is VSCode "locked" to a bundled version of typescript for performing error highlighting and intellisense?

(Edit: I figured out how to switch VSCode to use the package-level TypeScript version. I can now confirm with full confidence that the "next" version of TypeScript solves the issue I reported)

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Fixed A PR has been merged for this issue
Projects
None yet
Development

No branches or pull requests

3 participants