29

How can I get a variables name in typescript? I want something like this:

var name = "Foo";
alert(getVariableName(name)); //Prints "name"
Kenneth Bo Christensen
  • 2,256
  • 2
  • 18
  • 21
  • I've created a library that adds a `nameof` function: [ts-nameof](https://github.com/dsherret/ts-nameof). You can use it with parts of the language only available in TypeScript too (ex. interfaces and type aliases). – David Sherret Sep 17 '16 at 21:31
  • Does this answer your question? [Variable name as a string in Javascript](https://stackoverflow.com/questions/4602141/variable-name-as-a-string-in-javascript) – Michael Freidgeim Nov 22 '21 at 21:07

7 Answers7

23

Expanding on basarat's answer, you need to create function that takes as a parameter a function that will contain the access to your variable. Because in JavaScript you can access the code of any function it then becomes a simple matter of using a regex to extract the variable name.

var varExtractor = new RegExp("return (.*);");
export function getVariableName<TResult>(name: () => TResult) {
    var m = varExtractor.exec(name + "");
    if (m == null) throw new Error("The function does not contain a statement matching 'return variableName;'");
    return m[1];
}

var foo = "";
console.log(getVariableName(() => foo));
Titian Cernicova-Dragomir
  • 230,986
  • 31
  • 415
  • 357
  • If I'm not mistaken, for properties of objects this will return the class qualified name, for example: `Foo.bar`. To return only the property name, it might be feasible to return only the part of name after the last dot, using `m[1].substring(Math.max(0, m[1].lastIndexOf(".")))`. The `Math.max` call is used to handle the case when `lastIndexOf` would return `-1`, in which case the entire string should be returned (from index `0`). – John Weisz Aug 29 '16 at 08:15
  • Some minifications do not remove ";" from function body so it is safer to use new RegExp("return (.*)}"); and then replace ";" with empty string and trim it. – michal.jakubeczy Feb 23 '17 at 11:03
  • I've added a variation that allows for the full path to be retrieved. https://mrpmorris.blogspot.co.uk/2017/08/typescript-convert-lambda-expression.html – Peter Morris Aug 27 '17 at 10:25
  • 1
    @PeterMorris the original question was regarding a variable name, which wouldn't be qualified by anything else. Your code will get the property (or property path) that is accessed on the parameter. Which is also a very useful function, just the answer to a different question :) – Titian Cernicova-Dragomir Aug 28 '17 at 06:12
7

One approach is to store such values in an object:

var o = {
    firstName: "Homer",
    lastName: "Simpson"
};

We can't get the name of o, but we can get the names (or "keys") of its two properties:

var k = Object.keys(o);
console.log(k[0]); // prints "firstName"
Daniel Earwicker
  • 114,894
  • 38
  • 205
  • 284
  • 2
    If you don't have an object or don't want to create a named object the same could be expressed as `Object.keys({ name })[0]`. – AplusKminus Oct 19 '22 at 15:29
5

Expanding Cernicova-Dragomir's answer:

Expanding on basarat's answer, you need to create function that takes as a parameter a function that will contain the access to your variable. Because in JavaScript you can access the code of any function it then becomes a simple matter of using a regex to extract the variable name.

to also support a field of an object:

var varExtractor = new RegExp("(.*)");

export function getVariableName<TResult>(getVar: () => TResult) {
    var m = varExtractor.exec(getVar + "");

    if (m == null)
        throw new Error("The function does not contain a statement matching 'return variableName;'");

    var fullMemberName = m[1];
    var memberParts = fullMemberName.split('.');

    return memberParts[memberParts.length-1];
}

var foo = { bar: "" };
var varName = getVariableName(() => foo.bar ); //prints "bar"

Notice that I've deleted the "return" because it doesn't work on Node.js when targeting ES6.

Alon
  • 10,381
  • 23
  • 88
  • 152
4

TypeScript is JavaScript at runtime. So the same limitations as there apply : Get the 'name' of a variable in Javascript

However you can do stuff like

alert(getVariableName(()=>name)) 

Here you would parse the body of the function passed into getVariableName and get that as a string.

Community
  • 1
  • 1
basarat
  • 261,912
  • 58
  • 460
  • 511
  • 7
    However, TypeScript is compiled into JavaScript, so in theory it could support a `nameof(varibleName)` operator that will work during compilation time. I wonder why they didn't do it already. This is one of the benefits of having a compilation process, and TS should take full advantage of it. – user2173353 Nov 16 '18 at 12:39
1
//typescript
function getVarName(obj: object): string {
  const keys = Object.keys(obj);
  console.assert(keys.length == 1, 'key count must be 1');
  return keys[0];
}
const simpleName = 123;
console.log(getVarName({ simpleName }), simpleName);

or

//javascript
"use strict";
function getVarName(obj) {
    const keys = Object.keys(obj);
    console.assert(keys.length == 1, 'key count must be 1');
    return keys[0];
}
const simpleName = 123;
console.log(getVarName({ simpleName }), simpleName);

it will output

[LOG]: simpleName, 123

but i think it should be finished in compile duration will be better in instead of runtime

lisonge
  • 429
  • 4
  • 9
1

If the variable is part of a class/interface, there is a really simple solution:

function getFieldName<T, K extends keyof T = keyof T>(name: K): K {
    return name;
}

I.e. const name = getFieldName<SomeInterface>('some_field') provides a compile-time guarantee that name contains 'some_field', and some_field is a valid field of SomeInterface.

serg06
  • 2,027
  • 1
  • 18
  • 26
0

Look at my answer for JavaScript migrated to TypeScript:

const nameOf = (f: () => void) => (f).toString().replace(/[ |()=>]/g, '');

Examples:

nameOf(() => myVariable)             // myVariable
nameOf(() => myVariable.name)        // myVariable.name
nameOf(() => myVariable.name.length) // myVariable.name.length
nameOf(() => myVariable.name[10])    // myVariable.name[10]
nameOf(() => MySuperClass)           // MySuperClass
Yauheni Pakala
  • 868
  • 9
  • 16