GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Unexpected "property is not assignable to type 'undefined'" on dynamic assignment · Issue #61409 · microsoft/TypeScript

Unexpected "property is not assignable to type 'undefined'" on dynamic assignment #61409

New issue
Copy link
New issue
Copy link
Closed as duplicate
Closed as duplicate
Unexpected "property is not assignable to type 'undefined'" on dynamic assignment#61409
Copy link

Description

@DimaIT
Dzmitry Tolpekin (DimaIT)
opened on Mar 12, 2025
Issue body actions

🔎 Search Terms

strictNullChecks "not assignable" "to type 'undefined'"

🕗 Version & Regression Information

  • This changed between versions 3.3.3 and 3.5.1
    All newer versions have this behavior

⏯ Playground Link

https://www.typescriptlang.org/play/?#code/JYOwLgpgTgZghgYwgAgHIHsAmEAKV0AOAzsgN4BQyVycA-AFzIgCuAtgEbQDcl17DyImCigA5jwC+5cgnQghydCNGg4AG0YZseQiQC8ZCT1nywyMHCiiIYTVlz5iyA6SPS1N5AUcBGRgGsIAE90GDR7HScDAHI4aJ4LKxsAbW9CHwBdZ0VlVTVU3wyuZAB6EuQAdyV-IndPNIIAJgDg0PDtR31kWOiaEkCQsK0HXQTLazACwkasgyVgFRB1Kaai0vKAUSh8KGkTBQaiRgBBbbgggB4BtuHIogA+bOSi8hglZAAKfbMGxTDDgCUZF4VESExWsxyCzyEOKZWQWx25CkQA

💻 Code

interface NodeProps {
    a?: number;
    b?: string;
}

const original: NodeProps = {};
const target: NodeProps = {};

let prop1: keyof NodeProps = 'a';
target[prop1] = original[prop1]; // works

let prop2: keyof NodeProps = 'a' as keyof NodeProps;
target[prop2] = original[prop2]; // Error

const props: Array<keyof NodeProps> = [];
for (const prop of props) {
    target[prop] = original[prop]; // Error
}

🙁 Actual behavior

Got unexpected errors:

Type 'string | number | undefined' is not assignable to type 'undefined'.
  Type 'string' is not assignable to type 'undefined'.

🙂 Expected behavior

Should produce no errors

Additional information about the issue

Seems to be closely related to #59969 - disabling strictNullChecks option changes the error text, but essentially error stays the same.

Error produced with strictNullChecks:

Type 'string | number' is not assignable to type 'never'.
  Type 'string' is not assignable to type 'never'.

Activity

  1. nmain commented on Mar 12, 2025

    @nmain
    Nicholai Main (nmain)
    on Mar 12, 2025
    More actions

    This is intended behavior, and was changed in #30769 and documented as a breaking change in https://github.com/microsoft/TypeScript/wiki/Breaking-Changes#fixes-to-unsound-writes-to-indexed-access-types. The compiler only allows it when it can prove the key type is just the unit "a" and not "a" | "b".

    Reacted by Martin Johns
  2. DimaIT commented on Mar 12, 2025

    @DimaIT
    Dzmitry Tolpekin (DimaIT)
    on Mar 12, 2025
    Author
    More actions

    An error would be expected if we try to set the value of potentially different type, as described in the link you've provided.
    But in my example value types match, therefore it's not clear to me why such behavior is expected.

    interface A {
        a?: number;
        b?: string;
    }
    
    const original: A = {};
    const target: A = {};
    
    let prop = "a" as "a" | "b";
    target[prop] = 10; // Error - expected
    target[prop] = "str"; // Error - expected
    target[prop] = original[prop]; // Error - why?

    UPD:
    Also the issue is gone if we do exact same assignment, only inside a generic function:

    function write<K extends keyof A>(arg: A, key: K, value: A[K]): void {
        arg[key] = value;
    }
    write(target, prop, original[prop]); // now it works
  3. MartinJohns commented on Mar 12, 2025

    @MartinJohns
    Martin Johns (MartinJohns)
    on Mar 12, 2025
    Contributor
    More actions

    Also the issue is gone if we do exact same assignment, only inside a generic function:

    Be aware that this is (intentionally) unsound and allows invalid assignments: write<"a" | "b">({}, "a", "abc")

  4. nmain commented on Mar 12, 2025

    @nmain
    Nicholai Main (nmain)
    on Mar 12, 2025
    More actions

    But in my example...

    There's quite a bit of explanation in #30769, and in the many linked PRs from that, that explain this all in more detail.

    Also the issue is gone if...

    I'm not certain, but I believe this is a separate (although somewhat related) soundness issue. The type A[K] is evaluated as if it were a read, but then is allowed for a property write. Property writes are sometimes treated covariantly when they shouldn't be.

    The existence of one soundness hole does not imply that all soundness should be removed.

    Reacted by Dzmitry Tolpekin
  5. DimaIT commented on Mar 12, 2025

    @DimaIT
    Dzmitry Tolpekin (DimaIT)
    on Mar 12, 2025
    Author
    More actions

    There are some nice explanations indeed:

    As human beings, we know if the key is the same, so will the type retrieved, regardless of what types are involved, but this doesn’t automatically follow from the compiler’s perspective unless the compiler is explicitly programmed to track it.

    Even a workaround was proposed, but not implemented.

  6. Dzmitry Tolpekin (DimaIT)
    closed this as a duplicateof Cannot assign property to same type with generic key #32693 on Mar 12, 2025
  7. microsoft
    locked as resolved and limited conversation to collaborators on Oct 22, 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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      You are visitor 01402503 — GeezerVison does not store the pages you look up.
      Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.