microsoft / microsoft/TypeScript
Ability to pick setter types (instead of getter types) in a mapped type
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 111k
- Forks
- 14.4k
- Avg merge
- 1d 19h
- Merged PRs (30d)
- 117
Description
🔍 Search Terms
typescript extract setter types mapped type
✅ Viability Checklist
- 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 isn't a request to add a new utility type: https://github.com/microsoft/TypeScript/wiki/No-New-Utility-Types
- This feature would agree with the rest of our Design Goals: https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals
⭐ Suggestion
(original thread on Discord)
This might be a request for a new utility type, or a new language feature, because there seems to be no way to do it with current language features currently:
Given this type:
class Foo {
get foo(): number {...}
set foo(v: 'foo' | 'bar' | number) {...}
}
We want to derive a type like this:
type Derived = PickWithSetterTypes<Foo>
// result:
// {foo: 'foo' | 'bar' | number}
There seems to be no way to implement PickWithSetterTypes in userland.
📃 Motivating Example
When writing class-based JSX components (for example, custom elements are written as classes), the JSX property types are setters, not getters.
In this JSX expression:
return <some-element foo={123} />
The foo prop is a setter, and it is setting the property on the custom element, it is not reading the property from the element.
So, when we define a class component, for example:
class SomeElement extends HTMLElement {
get foo(): number {...}
set foo(v: 'foo' | 'bar' | number) {...}
someMethod() {... this method should not be included in JSX types ...}
}
customElements.define('some-element', SomeElement)
We need to pluck the properties that we want available in the JSX. For example, something along the lines of this:
declare module 'some-lib' {
namespace JSX {
interface IntrinsicElements {
'some-element': Pick<SomeElement, 'foo'>
}
}
}
Now, the problem is, when we try to set a valid value for the property in JSX, it will not work:
return <some-element
foo={'foo'} // Type Error: 'foo' is not assignable to number
/>
There should not be a type error, because the setter actually does accept the value 'foo'.
💻 Use Cases
- What do you want to use this for?
- Any situations where the setter types need to be extracted, for example JSX props
- What shortcomings exist with current approaches?
- it is impossible right now
- What workarounds are you using in the meantime?
- Workarounds could include providing separate named properties that can be extracted with template string types, but it is very cumbersome
With this method, now a utility type can be written that can use template string types to extract the setter type from the non-setter dummy property type, something like this:class SomeElement extends HTMLElement { set foo(v: this['_set_foo']) {...} get foo(): number {...} /** do not use this property, it is for types only */ _set_foo!: 'foo' | 'bar' | number }
TypeScript playground exampletype SomeElementJSXProps = JSXProps<SomeElement, 'fooBar' | 'foo'> // see linked playground below declare module 'react' { namespace JSX { interface IntrinsicElements { 'my-el': SomeElementJSXProps } } }
- Workarounds could include providing separate named properties that can be extracted with template string types, but it is very cumbersome
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the linked TypeScript Playground example and the issue's mapped-type, getter/setter, and JSX scenarios; the payload names no repository files, tests, or entry points. Define the design and acceptance cases around extracting setter types while preserving existing getter and JSX behavior, then identify the relevant compiler tests and implementation areas.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- compilers, developer-experience
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 28/100