7.0 regression: inherited members are sorted by position, so an empty subinterface changes assignability
Los mantenedores suelen responder en 1 día
@timurzvural ya está trabajando en esto.
Desde el 30/10/2026.
Evaluación
- Dificultad
- 4/5
- Tiempo estimado
- 3-5 días
- Aptitud para principiantes
- 25/100
- Tipo de issue
- Error
- Claridad
- Bien especificado
- Estado de actividad
- Estancado
- Stack tecnológico
- typescript
- Área
- compilers
Línea de trabajo
Start by reviewing getNamedMembers in 7.0.2 or createMemberLayout on main, then compare how inherited members are ordered in the reproduction's deep.ts. Run tsc --noEmit --pretty false deep.ts and check whether wideC produces the same assignability error as wideB; an open linked pull request indicates work is already underway.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
🔎 Search Terms
inherited members order, member order, property order, interface extends, empty subinterface, variance, unmeasurable, getNamedMembers, createMemberLayout, missing TS2322, 7.0 regression
🕗 Version & Regression Information
- This changed between versions 6.0.3 and 7.0.2
- Still present in 7.1.0-dev.20261030.1.
- microsoft/typescript-go#1987 (first in
@typescript/native-preview7.0.0-dev.20251031.1) fixed this for one level of inheritance (Bbelow), but not for two (C).
⏯ Playground Link
No response
(Reproduction repo can be found here - it doesn't seem like Playground runs an applicable version for this issue).
💻 Code
export const empty: C<string> = {};
declare const narrowB: B<{ a: string }>;
export const wideB: B<{ a: string; b?: number }> = narrowB;
declare const narrowC: C<{ a: string }>;
export const wideC: C<{ a: string; b?: number }> = narrowC;
interface A<T> {
inherited: () => T;
}
interface B<T> extends A<T> {
own: (x: T) => Required<T>;
}
interface C<T> extends B<T> {}
Run with tsc --noEmit --pretty false deep.ts and no tsconfig, since strict is the default. empty is only there for its message, which lists C's members in the order the checker compares them.
🙁 Actual behavior
With 7.0.2 and 7.1.0-dev.20261030.1, wideC compiles, though C adds nothing to B and the same assignment to B is an error:
deep.ts(1,14): error TS2739: Type '{}' is missing the following properties from type 'C<string>': inherited, own
deep.ts(3,14): error TS2322: Type 'B<{ a: string; }>' is not assignable to type 'B<{ a: string; b?: number | undefined; }>'.
The types returned by 'own(...)' are incompatible between these types.
Property 'b' is missing in type 'Required<{ a: string; }>' but required in type 'Required<{ a: string; b?: number | undefined; }>'.
🙂 Expected behavior
wideC is an error, like wideB, as in 6.0.3:
deep.ts(1,14): error TS2739: Type '{}' is missing the following properties from type 'C<string>': own, inherited
deep.ts(3,14): error TS2322: Type 'B<{ a: string; }>' is not assignable to type 'B<{ a: string; b?: number | undefined; }>'.
The types returned by 'own(...)' are incompatible between these types.
Property 'b' is missing in type 'Required<{ a: string; }>' but required in type 'Required<{ a: string; b?: number | undefined; }>'.
deep.ts(5,14): error TS2322: Type 'C<{ a: string; }>' is not assignable to type 'C<{ a: string; b?: number | undefined; }>'.
The types returned by 'own(...)' are incompatible between these types.
Property 'b' is missing in type 'Required<{ a: string; }>' but required in type 'Required<{ a: string; b?: number | undefined; }>'.
Additional information about the issue
C has no members of its own, so all of its properties are inherited, and they are sorted by declaration position (getNamedMembers in 7.0.2, createMemberLayout on main): inherited, declared in A, comes before own, declared in B. 6.0 takes C's inherited members from B in B's order, which puts B's own members first: own, inherited.
The order changes assignability through variance measurement, which relates C<Sub> to C<Super> and back member by member, stopping at the first member that fails. Required<T> in own marks T unmeasurable (the -?), but only when relating C<Super> to C<Sub>, and that direction fails at inherited first when inherited comes first. T is then measured plain invariant: --generateTrace shows B as [in out (unmeasurable)] and C as [in out]. Invariant, wideC passes because { a: string } and { a: string; b?: number } are each assignable to the other, while wideB gets the structural check that finds own's return types incompatible.
A fix: order inherited members by base type, and within a base type in that base's order, as 6.0 does.
Related, and already fixed on main: in 7.0.2 the order could also depend on other files. An inherited member counted as the interface's own when its text range fell inside the range of one of the interface's declarations in another file, such as a module augmentation, because isDeclarationContainedBy doesn't compare files, so a longer comment in an augmentation could make an assignment compile. #64915 replaced that check for classes and interfaces (first in 7.1.0-dev.20261024.1). I can share a repro if it matters for 7.0.
Found because a library relies on a -? member like own for exact assignments between instantiations of its schema type, and interfaces extending that type lost them on 7.0.
- Lenguaje dominante
- Go
- Estrellas
- 112k
- Forks
- 15.4k
- Merge medio
- 2 d 21 h
- PR fusionados (30 d)
- 126
Preparar el entorno
Inicia el contenedor de desarrollo del proyecto en tu navegador, con tu propia cuenta de GitHub.
- Sin Dockerfile ni archivo de Docker Compose
- Tiene una plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de microsoft/TypeScript
-
Won't Fix
Dificultad 2/5 1-3 horas Aptitud para principiantes 62/100
microsoft/TypeScript#65107 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
Native API: formatDiagnosticsWithColorAndContext drops related information without a file locationPosiblemente ocupada @timurzvural la tomó hoy. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 75/100
microsoft/TypeScript#65087 ·
Los mantenedores suelen responder en 1 día
-
TS7 LSP: documentHighlight returns nothing when the file path contains '@'Quizá libre de nuevo Un pull request para esta issue se cerró sin fusionarse. AbiertoBug
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
microsoft/TypeScript#64758 ·
Los mantenedores suelen responder en 1 día
-
Language server (tsc --lsp) exits with code 1 after `shutdown` and `exit`Posiblemente ocupada @rajnish-verma-22172 la tomó hace 12 días. AbiertoBug
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
microsoft/TypeScript#64742 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
Class names `eval` and `arguments` are not reported as invalid strict mode bindingsPosiblemente ocupada @dmety la tomó hace 26 días. AbiertoBug
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
microsoft/TypeScript#64661 ·
Los mantenedores suelen responder en 1 día
Todos los issues de microsoft/TypeScript
Issues similares
-
bug good first issue help wanted
Dificultad 2/5 1-3 horas Aptitud para principiantes 70/100
-
[mesheryctl] design delete fails when passing file or URL as positional argumentPosiblemente ocupada Un pull request vinculado a esta issue está abierto o ya se fusionó. Abiertocomponent/mesheryctl kind/bug language/go
Dificultad 2/5 1-3 horas Aptitud para principiantes 74/100
meshery/meshery#22772 · 3 comentarios ·
Los mantenedores suelen responder en 1 día
-
backend security size:S
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
limitlessprojects/Go-Hybrid#3342 ·
Los mantenedores suelen responder en 1 día
-
status/ready type/bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 65/100
buildpacks/pack#2733 ·
Los mantenedores suelen responder en 1 día