Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reflection Support for Types and Other Constructs #49610

Closed
5 tasks done
CoryGH opened this issue Jun 20, 2022 · 7 comments
Closed
5 tasks done

Reflection Support for Types and Other Constructs #49610

CoryGH opened this issue Jun 20, 2022 · 7 comments
Labels
Out of Scope This idea sits outside of the TypeScript language design constraints Suggestion An idea for TypeScript

Comments

@CoryGH
Copy link

CoryGH commented Jun 20, 2022

Suggestion

The specific issue I'm running in to relates to reflection on TypeScript type constructs, specifically with:

export enum eNum {
    FOO = 0,
    BAR = 1
}
export type foo = {
    bar: string,
    baz?: number,
    qux?: eNum
};

I would like to be able to discern:

{
    name: "foo",
    members: [
        {
            key: "bar",
            optional: false,
            definition: "string"
        },
        {
            key: "baz",
            optional: true,
            definition: "number"
        },
        {
            key: "bar",
            optional: true,
            definition: "eNum"
        }
    ]
}

In a more general sense, TypeScript is sorely lacking in a lot of reflection functionality, to the point getting a similar result from an enum looks something like:

public static parseEnum(enumType: { [id: string]: number|string }): string {
    let skipNext = false;
    let dontSkipNext = false;
    let ret = '{\n\t';
    let entryCount = 0;
    for (let entry in enumType) {
        let hit = false;
        if ((!skipNext) || dontSkipNext) {
            if (isNaN(Number(entry))) {
                // @ts-ignore
                dontSkipNext = !isNaN(enumType[entry]);
                skipNext = true;
                hit = true;
            } else {
                skipNext = false;
            }
        } else {
            skipNext = false;
            dontSkipNext = false;
        }
        if (hit) {
            if (entryCount > 0) {
                ret += ',\n\t';
            }
            ret += entry.toString() + ' = ';
            if (typeof enumType[entry] === "string") {
                ret += '"' + enumType[entry].toString() + '"';
            } else {
                ret += enumType[entry].toString();
            }
            entryCount++;
        }
    }
    ret += '\n}';
    return ret;
}

It would be nice if TypeScript supported reflection with 100% coverage to the point of .NET without all the hacks to work around it and the duplicate-code/boilerplate required when reflection simply isn't possible, such as in the case of type constructs.

🔍 Search Terms

Reflection, Types

✅ Viability Checklist

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

⭐ Suggestion

.NET-tier reflection.

📃 Motivating Example

See above.

💻 Use Cases

See above.

@MartinJohns
Copy link
Contributor

Duplicate of #3628.


[x] This feature would agree with the rest of TypeScript's Design Goals.

It does not agree with the TypeScript Design Goals. See non-goal 5, which mentions this explicitly.

Add or rely on run-time type information in programs, or emit different code based on the results of the type system. Instead, encourage programming patterns that do not require run-time metadata.

@CoryGH
Copy link
Author

CoryGH commented Jun 20, 2022

Add or rely on run-time type information in programs, or emit different code based on the results of the type system. Instead, encourage programming patterns that do not require run-time metadata.

With all due respect, that's not a wise philosophy. Restricting developers in what they can do is antithetical to JavaScript in general, but in this specific case is a true absurdity because reflection of types is a basic requirement to creating libraries which extend functionality and reduce boilerplate, which both JavaScript and TypeScript suffer from immensely.

@RyanCavanaugh RyanCavanaugh added Suggestion An idea for TypeScript Out of Scope This idea sits outside of the TypeScript language design constraints labels Jun 20, 2022
@RyanCavanaugh
Copy link
Member

Non-support of reflection is an intentional design goal; you're free to disagree with that but we've found it to work well so far.

@RyanCavanaugh RyanCavanaugh closed this as not planned Won't fix, can't repro, duplicate, stale Jun 20, 2022
@CoryGH
Copy link
Author

CoryGH commented Jun 20, 2022

@RyanCavanaugh What possible goal does intentional non-support of reflection have other than to harm the utility of the language?

@RyanCavanaugh
Copy link
Member

RyanCavanaugh commented Jun 20, 2022

Great question; not making the types of your program part of your runtime contract means we can do semantics-preserving type representation changes between releases (such as going from T & (A | B) to (T & A) | (T & B), which we did in the past) without fear of breaking the runtime behavior of your program. The ability to make those kinds of changes has been a necessary component of virtually all the innovation in the type system over the years.

@CoryGH
Copy link
Author

CoryGH commented Jun 20, 2022

Ah, so is this something where reflection is being saved for when TypeScript is more mature as a language and in turn would have less changes required for it?

@RyanCavanaugh
Copy link
Member

I don't think we'll ever stop innovating in the type system; it's where the value is. The future is far away and if things change we will of course re-evaluate. Meanwhile, projects like io-ts are doing a great job of providing ways to write the metadata in value space and generate types from that, which has proved to be a great approach.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Out of Scope This idea sits outside of the TypeScript language design constraints Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

3 participants