Skip to content

Missing type check in typed function parameter scenario #11895

Closed
@grantbowering

Description

@grantbowering

TypeScript Version: 2.0.3

Code

// A *self-contained* demonstration of the problem follows...

// this is from redux-typed
abstract class Action {
    type: string;
    constructor() {
        this.type = this.type;
    }
}

// this is from redux-typed
interface ActionClass<TAction extends Action> {
    prototype: TAction;
}

// we use this any-typed base class so we don't have to specify TAction and it can be polymorphic
abstract class ReductionBase<TState> {
    action: any;
    newValues: {(a):TState};
}

// this represents a potential reducer function to execute on an action
class Reduction<TState, TAction extends Action> extends ReductionBase<TState> {
    action: ActionClass<TAction>;
    newValues: (a:TAction) => TState;
    constructor(actionClass: ActionClass<TAction>,
                newValues: (action: TAction) => TState ) {
    super();
        this.action = actionClass;
        this.newValues = newValues;
    }
}

// this abstract class should specify that the type to Reduction<TState, TAction> is its TState
abstract class Store<TState> {

    memberVariable: TState; // this is just included to make a point later

    // this function is to instantiate compatible Reductions that match TState
    reduction<TAction extends Action>(actionClass: ActionClass<TAction>,
                                    newValues: (action: TAction) => TState)
    : Reduction<TState, TAction> {
        return new Reduction(actionClass, newValues);
    }
}

// type to become TState
interface ConcreteState {
    stateItemOne?: string[];
    stateItemTwo?: string[];
    stateItemThree?: string[];
}

// type to become TAction
class ConcreteAction extends Action {
    actionItemOne?: string[];
    actionItemTwo?: string[];
}

// implement Store<T> for ConcreteState
class ConcreteStore extends Store<ConcreteState> {

    reducer(state, action) {

        var reductionVar = this.reduction(
            ConcreteAction, (a) => {
                return {
                    // in Visual Studio 2015, I get compile-time type checking 
                    // and auto-complete in this body for members of a, but NOT 
                    // for members of this return type!

                    stateItemOne: a.actionItemNonexistent, // #1: this fails, as expected :)

                    stateItemNonexistent: a.actionItemTwo    // #2: this does NOT fail :(
                    // Interestingly enough, this TypeScript Playground does go as far as 
                    // to provide the correct auto-completion for these members, but the
                    // VS2015 intellisense does not even do that. :( 
                }
            });

        this.memberVariable = {
            stateItemNonexistent: [] // #3: this fails with the error "Object literal may 
                                     // only specify known properties", which was my expected
                                     // slash desired behavior at #2.
        }
    }

}

Expected behavior:

  1. Statement at "Updating some tests for resolved bugs #2" should check the return { object literal against the ConcreteState type, and display a compilation error, exactly as it does at "Revert "Updating some tests for resolved bugs" #3".
  2. Visual Studio 2015 should provide intellisense/auto-completion behavior for members of the return type at "Suggestion: 'protected' modifier #1/Updating some tests for resolved bugs #2", i.e. suggesting stateItemTwo and stateItemThree

Actual behavior:

  1. Statement at "Updating some tests for resolved bugs #2" does not fail the type check (despite the type of the resulting reductionVar being correctly detected and displayed as Reduction<ConcreteState, ConcreteAction>).
  2. Intellisense/auto-completion behavior of stateItemTwo/Three occurs on the TypeScript Playground, and in Visual Studio Code 1.4, but does NOT occur in Visual Studio 2015 (update 3 with TypeScript 2 installed).

Metadata

Metadata

Assignees

No one assigned

    Labels

    DuplicateAn existing issue was already createdFix AvailableA PR has been opened for this issue

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions