Description
Search Terms
compile time, logging, pragma
Suggestion
Add some statement which outputs a message to the console when running tsc
and which is not emitted in the JavaScript output. It should be possible to log literal values such as strings as well as information about types and generic parameters.
Use Cases
I've written a lot of code in D and it's probably my favorite language to work with, in spite of its flaws. D has the most wonderful, mature, and usable template system of any language I know of. (For the unaware: Templates are kind of like generics, except if generics could accept values and expressions computable at compile-time, not only types. Templates are like generics except more.)
One of the most essential features that helps keep D's mammoth of a template system so useable looks like this: pragma(msg, "My compiler message");
. When the compiler reaches this code, it will log out the string to the console along with its other status messages.
Of course, logging string literals is only a small part of its usefulness. What's really important is the countless times that I've used this tool to output information about template parameters I'm confused about. What's T
here? Let me add in a pragma(msg, T);
... Aha, T
is a uint
. No wonder my code doesn't work. Fix, fix... Problem solved.
I have felt the need for a feature like this in TypeScript so many times, particularly as a tool to help me to better understand compiler errors rendered opaque by T
identifiers all over the place, or to figure out what the heck ReturnType<my_function_with_a_non_trivial_inferred_return_type>
is so that I can actually identify and refer to this zany type in other places.
Note that when this logging statement is contained within a parameterized function or type or etc., the ideal behavior is for it to log its message once for every different combination of generic parameters that the enclosing scope receives.
Examples
The first mechanism I can think of is to add a new standard identifier which is used like a parameterized type. I don't know enough about the language innards to say if this is really an especially viable solution. I'm not really attached to this particular syntax proposal. But it's an idea.
ConsoleMessage<"This is a statically-known message string which will appear during compilation">;
ConsoleMessage<"Please tell me all about this type:">;
ConsoleMessage<T>;
function myFunction<T>() {
ConsoleMessage<"This message will be outputted exactly three times">;
ConsoleMessage<T>;
}
myFunction<boolean>(); // Logs for T = boolean
myFunction<number>(); // Logs for T = number
myFunction<string>(); // Logs for T = string
myFunction<string>(); // Does not log
Checklist
My suggestion meets these guidelines:
- 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, etc.)
- This feature would agree with the rest of TypeScript's Design Goals. (It would go a long way to actually accomplishing goal 5...)