Variant accessors for index signatures and mapped types
See original GitHub issueSuggestion
🔍 Search Terms
variant accessors index signatures record
✅ Viability Checklist
My suggestion meets these guidelines:
- This wouldn’t be a breaking change in existing TypeScript/JavaScript code
- This wouldn’t change the runtime behavior of existing JavaScript code
- This could be implemented without emitting different JS based on the types of the expressions
- This isn’t a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
- This feature would agree with the rest of TypeScript’s Design Goals.
⭐ Suggestion
Support for having Variant Accessors with index signature.
📃 Motivating Example
// Simple usage
interface NumberMap {
get [k: string](): number;
set [k: string](val: string | number);
}
const a: NumberMap = {}
a.test = '1';
a.test === 1;
// more complex
// makes number properties of an object to allow set `string`
type MakeStringAsNumber<T extends Record<string, any>> = {
get [ K in keyof T]: T[K]
set [ K in keyof T]: T[K] extends number ? T[K] | string : T[K]
}
declare const a: MakeStringAsNumber<{ a: boolean, b: number, c: string }>
a.b = '42'; // I want to have this avalible
a.c = '112'
// @ts-expect-error 'a' is boolean
a.a = '2'
💻 Use Cases
The use case for this feature is vue 3 reactivity.
In Vue 3 there’s Ref<T>
(simplified as { value: T}
) and Reactive<UnwrappedRef<T>>
(unwraps {value: T}
to T
, recursive)
This feature would allow us to generate a type which can accept a Ref<T> | T
Basically:
const r = ref({ a: 1} )
r.value.a = 1
const a = reactive(r)
a.a // 1
On a reactive
/ref
object the set in typescript must be UnwrappedRef<T>
which is not true, because when you assign to a reactive
it will unwrap the value:
const r = ref({a:1});
const a = ref({
r
}) // results in `{ r: { a: 1 } }`
a.r = r; // typescript error because `r` is `Ref<T>` instead of `UnwrappedRef<T>`, but it works at runtime.
Issue Analytics
- State:
- Created 2 years ago
- Reactions:43
- Comments:14 (1 by maintainers)
Top Results From Across the Web
Index signature with separate types for getters and setters
Variant accessors do not currently apply to index signatures or mapped types. There is an existing feature request at ...
Read more >Playground Example - Use Index Accessors for Index Signatures
This type uses an index signature to indicate that you can ask for any string and you will either get a string of...
Read more >Mapped Types - Learn TypeScript w/ Mike North
Mapped allow types to be defined in other types through a much more flexible version of an index signature. We'll study this type...
Read more >Google TypeScript Style Guide
Type System: Type Inference: Null vs Undefined: Structural Types vs Nominal ... Types / index signatures ({[key: string]: T}): Mapped & Conditional Types...
Read more >Overview - TypeScript
In TypeScript 3.4, the readonly modifier in a mapped type will ... If X contains a string index signature, keyof X is a...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
I don’t mean to be overly critical, but your API reads like your first language is Ruby. Proxy abuse like that doesn’t seem like the kind of thing TS should be encouraging. What’s wrong with
database.get("admin.settings.defaultPage")
? If you want to encode the database key hierarchy for type-checking, you can use conditional types to generate a union of template literal strings from an interface.Thank you for your example, this helps make my code much better. But I still believe that being able to get a Promise and set a value will make it even better.