Skip to content

Incorrect Type Inference for Array Properties in Recursive Type DefinitionsΒ #61394

@ahzvenol

Description

@ahzvenol

πŸ”Ž Search Terms

array type

πŸ•— Version & Regression Information

  • This is the behavior in every version I tried

⏯ Playground Link

https://www.typescriptlang.org/play/?ts=5.9.0-dev.20250310#code/C4TwDgpgBA4hzAgJwDwBUB8UC8UAUAlDlmgFCmiRQDK8iqmOUA3qVO1CgKpQQAeiAHYATAM5RMeAG4BDADYBXCAC58YJBCmq0RbFi4FVXNh268BEEeMmzFKqAFE+AY0XCI3ADRQAYgsHOwACWAPaCGIZQxgC+5JTQ1EEA5oLy6Fi4cAjI6VAAZDR0OZhx4NAAShAygUFSHoy4iSlpjAV4aOZCYlAhAEYAVhCBUAD8LFAaMsJhciBQANoA0lBBglAA1hAgIQBmEgC6qpXVwXXoS-tY0VCqzNEEpVTHNXUAgkhIMnO4z6ce758QCh-OtBCEAO7hDCPCpVF4QACyMjATF+tQ8SLAwMEoIhgm8ILBkIw0IoZSgAK+PhCSAc1QAFqi4X9KSB5gByHY0unOens-ZQAD0gqglVEITkdXEwBCFI+X2xuOJHK5tIZ-JhUEx1LVvKZJ3RmJV3PVAuFoog4sllqgMpoyVSchQmMVRPxUEJeJJxt1fIFBTuQA

πŸ’» Code

type Getter<T> = () => T

type Setter<T> = {
    <U extends T>(value: (prev: T) => U): U
    <U extends T>(value: Exclude<U, Function>): U
}

type Signal<T> = Getter<T> & Setter<T>

type Reactive<T> = Signal<T> & (T extends object ? { readonly [K in keyof T]: Reactive<T[K]> } : {})

type ReactiveArray = Reactive<Array<unknown>>

type ReactiveMap = Reactive<Map<unknown, unknown>>

type ArrayForEach = ReactiveArray['forEach'] // Resolves to Array<unknown>['forEach']

type MapForEach = ReactiveMap['forEach'] // Resolves to Signal<Map<unknown, unknown>>['forEach'] & {}

πŸ™ Actual behavior

The forEach type is inferred as Array<unknown>['forEach'], retaining the original Array method signature instead of being transformed into a Signal type like Signal<Array<unknown>['forEach']> & {}. This issue affects all Array properties.

πŸ™‚ Expected behavior

For ReactiveArray, defined as Reactive<Array<unknown>>, I expect ReactiveArray['forEach'] to be Signal<Array<unknown>['forEach']> & {}, similar to how ReactiveMap['forEach'] is inferred as Signal<Map<unknown, unknown>>['forEach'] & {}, reflecting the recursive application of Reactive<T>.

Additional information about the issue

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions