Skip to content

Suggestion: type property names as string literal types #7722

Closed
@alitaheri

Description

@alitaheri

Consider this interface:

interface A {
  foo: string;
  bar: Function;
}

With an operator such as membersof we can have this type:

type MembersofA = membersof A; // equivalent of type MembersofA = 'foo' | 'bar';

Some caveats:

  1. Deceleration merging: I think the compiler is smart enough to resolve all merged properties before building the type for membersof.
  2. Inheritance: If the compiler is smart enough to handle 1, this is a piece of cake 😄
  3. Index signatures: In case we have an interface like this:
interface A {
  foo: string;
  [property: string]: any;
}

The type should turn into: 'foo' | string. Although I'm not so sure about this.
4. new and function signature: I think these can be ignored safely:

interface A {
  new ();
  (bar: number): void;
  foo: string;
}
type MembersofA = membersof A; // 'foo'
  1. Other type constructs:
    • class: public members?
    • enum: members, should be easy. maybe even easy for constant enums
    • namespace: treated like interfaces
    • type alias, union/intersection: doesn't make sense, does it?

There are many use cases. immutable js is the best one:

import {Map} from 'immutable';

interface MapShape {
  foo: number;
  bar: string;
  baz: boolean;
}

const map = new Map<MapShape>();

map.set('blah', 1); // error, unless [other: string]: any; is added to MapShape

Accompanied by #6080 we can have type safety too:

map.set('bar', 1); // error: 1 is not string

Map would look like this:

class Map<T> {
   set(prop: membersof T, value: any): Map<T>;
}

// or with "Value of string literal type as property names" (#6080)

class Map<T> {
   set<U extends membersof T>(prop: U, value: T[U]): Map<T>;
}
// Although this might need to have the output of membersof T to be extensible!

This is easier to implementation than #1295.

Metadata

Metadata

Assignees

No one assigned

    Labels

    FixedA PR has been merged for this issueSuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions