Allow different properties between the JSX expression and component type
Ninguém assumiu esta issue ainda.
Avaliação
- Dificuldade
- 5/5
- Tempo estimado
- Mais de uma semana
- Facilidade para iniciantes
- 25/100
- Tipo de issue
- Funcionalidade
- Clareza
- Razoavelmente clara
- Status de atividade
- Estagnada
- Stack de tecnologia
- typescript
- Domínio
- compilers
Direção de pesquisa
A issue não nomeia arquivos de implementação nem testes. Comece revisando os designs propostos para JSX.convertProperties, os exemplos motivadores e os objetivos de design vinculados do TypeScript; em seguida, localize os pontos de entrada da verificação de tipos de JSX. A tarefa estará concluída quando o comportamento aceito e os limites de compatibilidade estiverem definidos com precisão suficiente para orientar a implementação e os testes.
Escrita pelo modelo de indexação a partir do texto da issue.
Descrição
Suggestion
🔍 Search Terms
- jsx functional component properties
- property type
- parameter type
- jsx property cast
✅ 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
Concept based on #14729
Introduce a new function to the JSX namespace called convertProperties (subject to change) which takes a component and returns an object representing its JSX props.
declare namespace JSX {
// today's behavior
function convertProperties<P>(component: (JSX.ElementClass & { new(): { props: P } }) | ((props: P) => JSX.Element)): P;
// alternatively, if this were to supercede IntrinsicAttributes rather than just working alongside it
function convertProperties<P>(component: (props: P) => JSX.Element): P & JSX.IntrinsicAttributes;
function convertProperties<P, T extends { props: P }>(component: JSX.ElementClass & { new(): T }): P & JSX.IntrinsicAttributes & JSX.IntrinsicClassAttributes<T>;
}
When the typechecker sees a component expression (e.g. <MyComponent prop={val} />), it will determine the types of the required properties by performing a virtual call to JSX.convertProperties with the provided component type and using the return type. For example:
type SignalProps<P> = { [K in keyof P]: () => P[K] };
declare namespace JSX {
function convertProperties<P>(component: ((props: SignalProps<P>) => JSX.Element)): P;
}
type MyProps = SignalProps<{
title: string;
count: number;
}>;
function MyComponent({ title, count }: MyProps) {
return <div>{title()}: {count()}</div>;
}
function App() {
// typeof MyComponent == (props: { title: () => string, count: () => number }) => JSX.Element
// typeof JSX.convertProperties(MyComponent) == { title: string, count: number }
return <MyComponent title="Hello, World!" count={3} />;
}
📃 Motivating Example
The Solid framework is very similar to React, but rather than tracking reactive dependencies with an explicit dependencies array like in React's useMemo and useEffect, Solid requires calling a function to retrieve the value of a piece of state, allowing for implicit dependency tracking based on which states were previously fetched the last time the memo/effect callback ran (see https://www.solidjs.com/guides/reactivity#introducing-primitives). It is a similar concept to Knockout's observables.
However, when it comes to component properties, Solid uses proxy dereferences instead of explicit function calls. This leads to a common footgun where destructuring the props object like one might do in React will prevent dependencies from being tracked (https://www.solidjs.com/guides/faq#why-do-i-lose-reactivity-when-i-destructure-props). An alternative design could have had the jsx factory function wrap every prop in a reactive getter before bundling them into the props object.
By separating the prop types between the component creation and the JSX where it's used, TypeScript would be able to support such a design in a new web framework.
💻 Use Cases
See above.
Another similar use case could be:
type DetailedProps<P> = {
[K in keyof P]: {
value: P[K];
prevValue?: P[K];
}
}
declare namespace JSX {
function convertProperties<P>(component: ((props: DetailedProps<P>) => JSX.Element)): P;
}
This feature would also allow performing the reverse operation of JSX.IntrinsicAttributes. For example:
declare namespace JSX {
function convertProperties<P>(component: ((props: P) => JSX.Element)): Omit<P, 'parent'>;
}
type PropsWithParent<T> = T & {
parent?: JSX.Element;
};
function MyComponent({ parent }: PropsWithParent<{}>) {
// ...
}
function App() {
return <MyComponent />;
}
Alternative Designs
Alternatively, a solution which is slightly less powerful but likely just as useful in 90% of cases could be to declare generic types on the JSX namespace like is done with JSX.IntrinsicClassAttributes<T>:
declare namespace JSX {
// same behavior as today
type TransformProps<P> = P;
// some use cases
type TransformProps<P> = { [K in keyof P]: P[K] extends () => infer R ? R : never };
type TransformProps<P> = Omit<P, 'parent'>;
// or in reverse, deriving JSX prop types via inference like in the earlier examples
type TransformProps<P> = SignalProps<P>;
type TransformProps<P> = P & { parent?: JSX.Element };
}
- Linguagem predominante
- Go
- Estrelas
- 111k
- Forks
- 14.4k
- Merge médio
- 1d 19h
- PRs com merge (30d)
- 117
Guia de contribuição
Primeiros passos
- Leia a issue inteira e depois o guia de contribuição do projeto.
- Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
- Faça um fork do repositório e trabalhe em uma branch.
- Abra um pull request que referencie o número da issue.
Mais de microsoft/TypeScript
-
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 88/100
microsoft/TypeScript#64322 · 2 comentários · 1 reação · 2 responsáveis ·
-
Possible Improvement
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 78/100
microsoft/TypeScript#64278 · 1 comentário · 1 reação ·
-
Docs
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 70/100
microsoft/TypeScript#64118 · 1 comentário ·
-
Dificuldade 1/5 Menos de uma hora Facilidade para iniciantes 88/100
microsoft/TypeScript#64094 ·
-
Docs
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 76/100
microsoft/TypeScript#63959 · 5 comentários ·
Todas as issues de microsoft/TypeScript
Issues semelhantes
-
optimization optimization:agents-md-curator
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 86/100
githubnext/gh-aw-cao#13143 ·
-
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 84/100
blinklabs-io/bursa#904 ·
-
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 84/100
yanet-platform/ipfw-go#129 ·
-
bug confmap/provider/googlesecretmanagerprovider needs triage
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 72/100
open-telemetry/opentelemetry-collector-contrib#51273 · 2 comentários ·
-
bug: AI Gateway client filter lists "Unknown" twice when NULL and literal Unknown clients coexist Abertabug
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 90/100