nameof keyword!

Topics: General
Oct 25, 2013 at 2:08 PM
TypeScript aims to bring type annotation to javascript. But there are lot of situations where you still need to use string literal. One of such are frameworks for MVC, MVVM, where you have methods like get and set that accept string parameter for property name you wish to change. But this is not refactoring friendly, because you don’t get any help from compiler. The same problem existed in C# before version 5, where you typically use lambda expressions to get current property name used to trigger notification event.

Keyword nameof simply returns string literal name of variable, type. Something like this:
var a;
nameof(a); // => "a"

interface IFoo {
    func();
}
nameof(IFoo); // => "IFoo"
nameof(IFoo.func); // => "func"
For getting current function name you could use nameof(.)
function move()
{
    var name = nameof(.); // returns "move"
}
For getting full type path you use nameof(..)
module A {
    class C {
        move() {
            var fullName = nameof(..); // returns "A.C.move"
        }
    }
}
This can be very useful for logging:
function move() {
  sys.throwNotImplemented(nameof(..));  
           // throws NotImplemented exception with full orign name
}
There are other countless situations where this can be used. And also generated javascript is clean, you generate only string literals.
Coordinator
Oct 25, 2013 at 6:58 PM
Trying to understand the suggestion. Looks like you want syntactic sugar for typing in a symbol name that is known statically, rather than dynamically.

This sounds helpful, though perhaps not strong enough value to put in the language itself. We have a high bar for new expression types because we try to maintain a very close compatibility with ECMAScript, the standard behind JavaScript. Introducing new expressions makes us incompatible in those cases.
Oct 31, 2013 at 2:38 PM
It's not exactly what you're asking for, but you can extract some name information with this helper function:
function getName(ent: any): string {
        if (typeof ent == "string") return ent;

        if (ent.constructor && ent.constructor.name != "Function") {
            return ent.constructor.name || (ent.toString().match(/function (.+?)\(/) || [, ''])[1];
        } else {
            return ent.name;
        }
    }
It works with class constructors and object instantiated via this class constructors:
module A {
    export class Foo{}
}

getName(A.Foo);         // => "Foo"
getName(new A.Foo());   // => "Foo"
Nov 4, 2013 at 2:36 PM
prohazko, thanks for reply. I’m completely aware that you can get the name of the function with some helper method, but this is not very concise solution. It has performances issues, portability is little tricky and most important I would like that generated js will have simple literal string.

The following ModelView class:
class Foo extends ModelView {
    get name() {
        return this.getProp(nameof(.));
    }
}
will be equal to writing this ts code (the name of the keyword is unimportant, I just use nameof(.), which returns current function name):
class Foo extends ModelView {
    get name() {
        return this.getProp("name");
    }
}
To summarize, there are lot of information that are known to compiler and it will be nice that some of them get there way to runtime, so that you can used them from ts code. For example I also miss line number, file name… which will give me tremendous power in debugging, logging scenarios, especially with bigger projects.
Nov 4, 2013 at 9:01 PM
jonturner wrote:
Trying to understand the suggestion. Looks like you want syntactic sugar for typing in a symbol name that is known statically, rather than dynamically.

This sounds helpful, though perhaps not strong enough value to put in the language itself. We have a high bar for new expression types because we try to maintain a very close compatibility with ECMAScript, the standard behind JavaScript. Introducing new expressions makes us incompatible in those cases.
@jonturner Is that going to remain the case after ECMAScript 6 is finalized as well? It seems to me that after that point it will be impossible to maintain forward compatibility with a hypothetical future ECMAScript 7 without effectively ending TypeScript language design. You guys have stated repeatedly that you'd like to do async/await, which would mean a very fundamental syntax addition. I think the benefits now of what TypeScript is and could become should outweigh concerns over what a standards committee might do 5, 10 years down the road.

Rather than shutting down the language design; a far more sensible solution to me would be to do what some other mainstream languages do but MS has largely been hesitant to do- introduce breaking changes between major versions. That way you don't cripple your own language design efforts while still keeping the flexibility to change syntax if a future ECMAScript 7 has a collision.
Coordinator
Nov 11, 2013 at 5:58 PM
@MgSam

That's why we keep the expression-side of the syntax fairly lightweight. We'll probably only pull in things that have high value, and we'll do this in a way that the ECMAScript committee and the TypeScript community can work together.

That's not to say we won't put in features that make sense for TypeScript users, but we'll try do it in a way that always has an eye to compatibility.

I'm uneasy about taking on breaking changes, as that's always a mixed bag when a major version causes incompatibility, and something most languages try to avoid.
Feb 19, 2014 at 2:44 AM
jonturner wrote:
Trying to understand the suggestion. Looks like you want syntactic sugar for typing in a symbol name that is known statically, rather than dynamically.

This sounds helpful, though perhaps not strong enough value to put in the language itself. We have a high bar for new expression types because we try to maintain a very close compatibility with ECMAScript, the standard behind JavaScript. Introducing new expressions makes us incompatible in those cases.
I would like to +1 this feature request. It is in keeping with the spirit of TypeScript, which is to enable application-scale JavaScript development. It is easy to generate the equivalent idiomatic JavaScript code because the compiler knows the name of the identifier at compile time.

In my case, I'm using Azure Mobile Services and I have DAO classes that pass the name of the identity primary key column to the super constructor so it can remove that column from the update method. I have matching type definitions for all my tables. For example:
declare module MyApp.Data.Model {
    export interface IUserSession extends IEntity {
        user_session_id?: number;
        user_id: number;
        jwt_token: string;
        device_type: string;
        device_token?: string;
        start_time?: Date;
        end_time?: Date;
    }
}
In my DAO, currently I have to pass the string 'user_session_id' to the base DAO's constructor. I'd much rather pass nameof(MyApp.Data.Model.IUserSession.user_session_id) which the TypeScript compiler can easily resolve to 'user_session_id'. It will give me code completion and refactoring support.

This is just one example. One of the big things about JavaScript that allows us to shoot ourselves in the foot is string-based APIs. The nameof operator/function would take care of a lot of these cases, thereby significantly improving static typing of TypeScript.
Feb 19, 2014 at 9:06 AM
A similar feature (but far more generic) is present in C# - expression trees - http://msdn.microsoft.com/en-us/library/bb882637.aspx

Expression trees make AST information available at runtime so it would be easy to implement nameof using them. The downside is of course increased compiler complexity.
Feb 19, 2014 at 1:25 PM
wiktork wrote:
A similar feature (but far more generic) is present in C# - expression trees - http://msdn.microsoft.com/en-us/library/bb882637.aspx

Expression trees make AST information available at runtime so it would be easy to implement nameof using them. The downside is of course increased compiler complexity.
@wiktork I think the idea is to have the information substituted at compile time rather than run time. The benefit of such is that the cost of implementation is far less and the cost of usage in your code is free.

IMO, C# also needs more of this type of information available at compile time. See the long-storied infoof operator.
Feb 20, 2014 at 2:10 AM
I concur. Static type checking is in the sprit of TypeScript. Adding runtime features goes against what TypeScript is all about.
Feb 20, 2014 at 9:53 AM
@MgSam Yes, you're right - it's more similar to the infoof operator than expression trees.

Reading the article that you've attached may explain why nameof is not implemented in TS and infoof in C#:
Eric: (...) we have a very limited time and money budget for design, implementation, testing, documentation and maintenance, so we want to make sure we’re spending it on the highest-value features. This one has never made it over that bar.