Skip to content

Be able too let foo: ObjType.propType instead of let foo: ObjType["propType"] #30267

Closed

Description

@ozra

Search Terms

I had no clue what to search for to find a duplicate of this feature request — I've tried these, along with variants of taking of words / etc.:
subscript type, reference type property, refer to interface property sub type, access product type member , type alias property access

Suggestion

At the moment, it's possible to:

type Foo = { pub: string, bar: Bar }
/* ... */
let a_bar: Foo["bar"]

Unless a conflict in syntax and parsing arise implementing it, I would find it more than reasonable for the syntax to mirror that of property access of objects, also mirroring namespace member accessing. Like so:

type Foo = { pub: string, bar: Bar }
/* ... */
let a_bar: Foo.bar

Use Cases & Examples

I've come to do these kinds of things A LOT:

export type UnionizePropTypes<T> = T[keyof T]

export const ThingRecordKind = {
    STATIC: 0 as 0,
    ARC: 1 as 1,
    EAVESDROPPER: 6 as 6,
}

export type ThingRecordKind = typeof ThingRecordKind & {
    ANY: UnionizePropTypes<typeof ThingRecordKind>
}

/* 
DON'T REPEAT YOURSELF!

type ThingRecordKind = {
    STATIC: 0;
    ARC: 1;
    EAVESDROPPER: 6;
} & {
    ANY: 0 | 1 | 4 | 5 | 6 | 9;
}
*/

function make_thingie_record(thing_kind: ThingRecordKind["ANY"]) {
    // do stuff
}

make_thingie_record(ThingRecordKind.ARC) // const table used

Above example is simplistic, the style of using literal objects as source of auto derived types excels with React and especially Redux, where I can get fully typed dispatch-fn with IDE hints for actions and their arguments, etc. from only ever defining the default states, and the reducers hashed on objects, so don't say "use enums" because of above example.

Checklist

My suggestion meets these guidelines:

  • This wouldn't be a breaking change in existing TypeScript/JavaScript code — can't see how
  • 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, etc.)
  • This feature would agree with the rest of TypeScript's Design Goals.

Activity

  1. RyanCavanaugh commented on Mar 8, 2019

    @RyanCavanaugh
    Member

    The behavior here is that a dotted name a.b.c.d in a type context always refers to the type d in the a.b.c namespace. The distinction is already very important because e.g.

    // foo.ts
    export class C { }
    
    // other file
    import * as X from "./foo";
    var t: X.C;

    means the instance type of the C class, not the constructor function itself.

    Changing the behavior here would either be a breaking change for code, or mean that a lookup like a.b.c would be ambiguous (which means code becomes fragile to the introduction of identifiers it shouldn't care about)

  2. typescript-bot commented on Mar 10, 2019

    @typescript-bot
    Contributor

    This issue has been marked 'Working as Intended' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

  3. ozra commented on Mar 12, 2019

    @ozra
    Author

    A missed. I saw the type ThingieRecord more like a "generalized form of enum", sort of, but of course, not enum - just looking into type the same way.

    Ryan Cavanaugh (@RyanCavanaugh) To be honest, and excuse my dumbness here, but I'm missing the conflict above, hmm :-/

    Can there be anything else in a type Foo = {bar: Bar} that would conflict when doing Foo.bar? A namespace Foo parallel in lookup scope with the type, is that it?

  4. RyanCavanaugh commented on Mar 12, 2019

    @RyanCavanaugh
    Member

    A namespace Foo parallel in lookup scope with the type, is that it?

    Correct, though there are other ways to get namespace-like things (for example, an import)

  5. locked as resolved and limited conversation to collaborators on Oct 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Working as IntendedThe behavior described is the intended behavior; this is not a bug

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions