Skip to content

Uncaught uninitialized class member with Symbol key #40617

Closed

Description

@soul-codes

TypeScript Version: 4.1.0-dev.20200917

Search Terms:
symbol class member uninitialized

Code

const Foo = Symbol()

class WithFoo {
  [Foo]: any[]; // this shouldn't be allowed without an initialization in a constructor
  Foo: any[]; // compare with this, which errors as expected
}

console.log(new WithFoo()[Foo].length) // uncaught uninitialized symbol member, oops

Expected behavior:
An error like Property 'Foo' has no initializer and is not definitely assigned in the constructor should also be emitted for the symbolic property Foo.

Actual behavior:
No such error is thrown.

Playground Link:
here

Activity

  1. a-tarasyuk commented on Nov 9, 2020

    @a-tarasyuk
    Contributor

    isPropertyInitializedInConstructor doesn't support ElementAccessExpression, only PropertyAccessExpression.

    function isPropertyInitializedInConstructor(propName: Identifier | PrivateIdentifier, propType: Type, constructor: ConstructorDeclaration) {
        const reference = factory.createPropertyAccessExpression(factory.createThis(), propName);
        setParent(reference.expression, reference);
        setParent(reference, constructor);
        reference.flowNode = constructor.returnFlowNode;
        const flowType = getFlowTypeOfReference(reference, propType, getOptionalType(propType));
        return !(getFalsyFlags(flowType) & TypeFlags.Undefined);
    }

    I think isPropertyInitializedInConstructor can be extended to use both ElementAccessExpression and PropertyAccessExpression, however, I'm not sure that getFlowTypeOfReference can resolve the right type for ElementAccessExpressions with Identifiers.

    const Foo = Symbol()
    class WithFoo {
      [Foo]: any[];
      ["prop"]: any[];
    
      constructor() {
        this[Foo] = []; ??
        this["prop"] = []; // Works
      }
    }

    Andrew Branch (@andrewbranch) What do you think?

  2. andrewbranch commented on Nov 13, 2020

    @andrewbranch
    Member

    Oleksandr Tarasiuk (@a-tarasyuk) you’re right, that would require #36230. Maybe the current behavior is intentional, then, as we’re looking at a choice between always¹ issuing the uninitialized error or never issuing it. 😕

    ¹ “always,” unless the initialization is on the class field itself, or the error is suppressed with !. These are pretty good as workarounds go, but I’m not sure they’re good enough to merit this change.

  3. andrewbranch commented on Nov 13, 2020

    @andrewbranch
    Member

    I don’t know though, it seems like issuing the error when there is no constructor would be better than nothing...

  4. locked as resolved and limited conversation to collaborators on Oct 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugA bug in TypeScript

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions