Repository: TypeScript
Issue: Mapped type with enum keys emits string keys in d.ts type, but uses enum keys in .ts type
Labels: Bug,Help Wanted

### 🔎 Search Terms

mapped type, enum, declaration

### 🕗 Version & Regression Information

- This is the behavior in every version I tried


### ⏯ Playground Link

https://www.typescriptlang.org/play/?ts=5.6.3&ssl=25&ssc=36&pln=25&pc=1#code/KYOwrgtgBAYg9nKBvAUFKBBKBeKByAQzwBo0oAhHfAIxJQF8UATYAYwBsCAnYKAMzAhWAFwCWcEPwQAeACoA+ABTcA5gC4osgJQbZBFSuBMAqiHEg58gNwoUwgJ4AHXnoNHT5y1SRQA2gGkoUUkAa2B7OD5NAF0NHzD7DX9iKAA3AnYwYF0A6Kh6fN8EyJibYAAPRzguYShWCQBnWuFgJqo+BEVUdF94OAA6DFj8Oh6+-vJhgEZSei0bFAB6RahhAAteBKgGgjEGvlFWqTgURRam-q2dvYOjvvmllYIQJjrn7YB3UWFWNagv9ZwMC1YBcLjVFANAG-KBnVrCS7hLTIMisAgNXjjDAaag8AghGzoNEY2AICY4vEEsgsPgEMDsYRqMjoZZQQCg5NsCHxgMzYedatdRPtDg0oCBgKlQQ9GLZFgAqOVQAC0KtVavVGs1UDli1sj1WayFQVFYAawRUBt4hnFXF2RlWTiOfHB0HWvH6TH6wgaKQAVqbajwQAQIPbhIgCKk4KJXhx0Ws7I7NPpDCYzBIACKyADKXlw3XQfkCwSgxSismGBcLhYSSUJ1cL6Uy2U0uXr6HoNnoRXCJQrZUq1VqLDjPDqjWa8Kz2d0Kfc6ZA0+kVagBA0TS45vbUGoGnAEGooK71llKzdpfCUCYcCOIDgAt2Qr49lJJzhTWniJfguFdwQD1ZZ5Y3eKFvhhAE1iBEEwQhUCfj+d9hE-BJkQLYlMTJbEd0pet0NfclsOAfF6xpOkGSZatWUAGXIoFBcEuAaXlEM5G4RTFCUpS7IA

### 💻 Code

```ts
enum Foo {
  A = 'a',
  B = 'b',
}
declare function foo<T>(arg: T): TaggedUnion<T>;

type TaggedUnion<T> = { [K in keyof T]: { key: K, value: T[K] } }[keyof T];
export const test = foo({
  [Foo.A]: '',
  [Foo.B]: 1,
});

// the key satisfies foo
(test.key satisfies Foo);
// and can switch without error
switch (test.key) {
  case Foo.A: break;
  case Foo.B: break;
  default:
    // ✅ safe
    (test satisfies never);
}


/** ---------------------------- */


// this is using the generated types from the .d.ts, just renamed to avoid clash
type TaggedUnionDTS<T> = {
    [K in keyof T]: {
        key: K;
        value: T[K];
    };
}[keyof T];
export declare const testDTS: TaggedUnionDTS<{
    a: string;
    b: number;
}>;

// the key does not satisfy Foo
(testDTS.key satisfies Foo);
// and can switch without error
switch (testDTS.key) {
  case Foo.A: break;
  case Foo.B: break;
  default:
    // ❌ errors
    (test satisfies never);
}
```


### 🙁 Actual behavior

When the above code is used and referenced directly via `.ts` files (i.e. in the IDE) then it all works as expected. TS is able to understand that the `.key` property is `Foo` and so it understands that the `switch` refines the variable and so in the `default` the variable correctly refines to `never`.

However when you consume the code via the `.d.ts` output - the relationship with `Foo` is lost entirely and so the same `switch` now is no longer able to refine the variable and so in the `default` the variable has not refined at all.

### 🙂 Expected behavior

Either `.d.ts` code should include the relationship with `Foo`, or the `.ts` code should not have a relationship to `Foo`. I.e. the behaviour should be consistent between the two.

### Additional information about the issue

An engineer encountered this at Canva.
The `test` variable was declared in a file that was previously within the same project as the `switch`.
During a refactor they moved the `test` variable to a new project, causing the CI typecheck to switch from using the `.ts` directly to using the `.d.ts`.

This caused the switch to not refine, causing a TS error on the default case.