microsoft / microsoft/TypeScript

Ability to pick setter types (instead of getter types) in a mapped type

Open
#60,162 3 comments 5 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Awaiting More Feedback Suggestion
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
⭐ 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
  1. What do you want to use this for?
    • Any situations where the setter types need to be extracted, for example JSX props
  2. What shortcomings exist with current approaches?
    • it is impossible right now
  3. 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
      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
      }
      
      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:
      type SomeElementJSXProps = JSXProps<SomeElement, 'fooBar' | 'foo'> // see linked playground below
      
      declare module 'react' {
          namespace JSX { interface IntrinsicElements { 'my-el': SomeElementJSXProps } }
      }
      
      TypeScript playground example

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.