Skip to content

Allow to directly reference the types associated with interface properties #4555

Closed
@rotemdan

Description

@rotemdan
interface A {
    prop: {
        x: number;
        y: number;
    }
}

Trying to associate the type of prop with a variable would lead to an error:

let p: A.prop; // Error: cannot find namespace A

Aside from anonymous object interfaces, it could also be allowed for function types:

interface A {
    func(arg: number): string
}

let f: A.func; // type of f is now func(arg: number): string
f = (arg: number) => "hello"; // OK

Primitive types:

interface A {
    prop: boolean;
}

let val: A.prop; // type of val is now boolean
val = true; // OK

And also when the types are nested:

interface A {
    outerProp: {
        innerProp: {
            x: number;
            y: number;
        }
    }
}

let p: A.outerProp.innerProp; // type of p would now be {x: number, y:number}
p = { x: 42, y: 24 } //OK

The current workaround (the best that could I find, at least [edit: I added an additional one that uses typeof in the next comment]) is to define the type of prop as a named interface or alternatively use the type keyword.

interface PropInterface {
    x: number;
    y: number;
}
// Or, alternatively:
type PropInterface = { x: number, y: number };

interface A {
    prop: PropInterface;
}

let p: PropInterface; // OK

But that isn't always necessary or elegant, especially if the types are nested or generic (short example below).

This can also be extended to types defined through the type keyword or when using typeof SomeClass. Or even with generics:

interface A<T> { 
    prop: { func: (val: T) => T } 
}

let f: A<number>.prop.func // working around this may be possible, but wouldn't be pretty.

A real-world use case I encountered was casting a value into the type of an interface member from a union that includes it (this happened when thinking about issues with assignability of merged/intersected types):

let merged: A merge B; // Also happens with intersection: A & B
let obj: A;
obj.prop = <A.prop> merged.prop; // the type of merged.prop is the union A.prop | B.prop

// Edit: It turns out that a relatively simple workaround is possible with the 'typeof' operator, 
// that is explained in the next comment:
obj.pro = <typeof obj.prop> merged.prop;

@RyanCavanaugh Too Complex? Perhaps at least keep it as an option for the future?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Needs ProposalThis issue needs a plan that clarifies the finer details of how it could be implemented.SuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions