Repository: TypeScript
Issue: Auto-completion fails when key type is aliased
Labels: Suggestion,Help Wanted,Domain: Completion Lists,Experience Enhancement

# Bug Report

### 🔎 Search Terms

autocomplete, autocompletion, generic, keyof

### 🕗 Version & Regression Information

- This is the behavior in every version I tried, and I reviewed the FAQ for entries about auto-completion

### ⏯ Playground Link

[Playground link with relevant code](https://www.typescriptlang.org/play?ts=4.5.4#code/PTAEBEEsGcEMBt4HsDu1SwHYE9QAcAnJPAUwIBdIT1JNQAVAQQGNyBXBUcgC1nIwIlQmJP1oMAsAChy2UqACiAD1it42ADz0ANAxbsEAPlABeBqABkoAEolmSAgBMNy5vDaOSGgNYlsSADM9Vg54XV9-IPpDXUwSADcyQwBuaWlZeXAUWAIAgDlYAFshMwBycCRmUtAAH1BSgHECNkK8bGq60oAJWDw2jvqAZXgSEn7a+oAhWGhuALZ4AdLBuJIAL3aJ8uI-UtSpaRBQQBWyQHg-0EY2ciQAWntWkcokOgCHUEds3OEi6nekakwpX4KAc3mknjcOSE80wrEgz3wM2gPCIbAA5twsjkAow0dQAIwaaSgPR49AkJTkEiYRzoZSqcjqDQAb1AAG0IqBxFjcgVigBdAD8AC5hC0AEZkUAAX10TDJhmJoCOJNVavVGs1JIAerq9XqlSqtcaTQxuDAuegeEJnup3pAAgEyNTmEJJeQUKM6Nb3nZ4Dk+PDMNBpIYABSwMmi+XUACU0dx1H2hzAgFByC5XW73PCPIOgEEEbwhqS0Km5VRCHn5H4AWV6oGZSoqzFFWGwyVATRabVbOA7PT62F77dAw1GPYwfdA01m83gw47K1GGwXEB2Q8n7ek0vBfqhoBhcIReCRKKQ6MxnxxZIATESpCSY+TKdTaYoVGpNKyOX4uXQIoEEBXnyJB1ngQqipgEpSrKpLUIqD7KmApooRq+roRhBpSOGkbUAmZLxnB0DJlIRxnNOVxcvwjj-NAgLAqCXJBJ6oAUuQBAMqAABEAFBFWIFgVxf7XBgXByCQ6TiUB2ICb0ADSv5mLx0m8rWvT7BC-qCAebCwk8dAntAyLcKiGJVom0AAMz3o+FmsS+NJ0h+jJfuynLcsBal4Ap2AQWKhSSgQMpyhZCEkkaqGRZh0WhhGUZEYRT4kWR5wAJL8Ag0BIH8AJAvmjEoJAPCiSImA3KWZABBWYmkJJmSecUYH0FJZi2PYTg+H4gH8V5ujxEgkCOCku6Qtph76YiRlnhe5lkgALDZRH2VSjnvgyTLfu5-5dXxDWgb0zWkH5UEBTBIUKoayGRVF0W3fqsW4dA+Fxs9xHSEAA)

### 💻 Code

<!-- Please post the relevant code sample here as well-->
```ts
// Disallows any properties in TActual that are not in T
type Exactly<T, TActual> = T & Record<Exclude<keyof TActual, keyof T>, never>;

type DwarfName = 'Doc' | 'Grumpy' | 'Happy' | 'Sleepy' | 'Bashful' | 'Sneezy' | 'Dopey';

// ⛔️ Auto-completion for dwarf names doesn't work
declare function passthroughDwarfAges1<
  TAges extends Exactly<{ [key in DwarfName]?: number }, TAges>
  //                              ^^^^^^^^^
  //                              This is the only difference between the declarations
>(ages: TAges): TAges;

// ✅ Auto-completion works
interface DwarfNameMap {
  Doc: any; Grumpy: any; Happy: any; Sleepy: any; Bashful: any; Sneezy: any; Dopey: any;
}
declare function passthroughDwarfAges2<
  TAges extends Exactly<{ [key in keyof DwarfNameMap]?: number }, TAges>
  //                              ^^^^^^^^^^^^^^^^^^
>(ages: TAges): TAges;

// ⛔️ But it doesn't work if we extract "keyof DwarfNameMap" into a type
type DwarfNameMapKey = keyof DwarfNameMap;
declare function passthroughDwarfAges3<
  TAges extends Exactly<{ [key in DwarfNameMapKey]?: number }, TAges>
  //                              ^^^^^^^^^^^^^^^
>(ages: TAges): TAges;

// ⛔️ It also doesn't work with a non-interface type
type DwarfNameMapType = Record<keyof DwarfNameMap, void>;
declare function passthroughDwarfAges4<
  TAges extends Exactly<{ [key in keyof DwarfNameMapType]?: number }, TAges>
  //                              ^^^^^^^^^^^^^^^^^^^^^^
>(ages: TAges): TAges;
```

### 🙁 Actual behavior

This code snippet contains four almost identical declarations for a function `passthroughDwarfAges`, which is meant to be called like this: `passthroughDwarfAges({ Doc: 64, Happy: 58 })`. The only difference is the exact syntax for the type of the key.

While typing dwarf names, I get auto-completion on declaration 2, but not on 1, 3, or 4.

### 🙂 Expected behavior

Declarations 3 and 4 are virtually identical to declaration 2. The only difference is that declaration 3 extracts `keyof DwarfNameMap` into a named type, while declaration 4 uses a type instead of an interface for `DwarfNameMap`. Given that declaration 2 gives auto-completion, I'd have expected declarations 3 and 4 to auto-complete, too.

And I'd have *hoped* that the very similar but much more idiomatic declaration 1 should work, too. 🙂