Reputation: 133
In C# there is the posibility to get the name of an object property as a string value.
nameof(object.myProperty) --> "myProprty"
Can this be done in Javascript/Typescript?
Object.Keys() is the only thing i found, but it gives me all the keys.
Example what I want to achieve:
export interface myObject {
myProperty: string;
}
console.log(myObject["myProperty"]);
Let's say I change my interface for some reason to:
export interface myObject {
myPropertyOther: string;
}
console.log(myObject["myProperty"]); // This will not give an error on build
So I want to have something like this:
console.log(myObject[nameOf(myObject.myProperty)]
// This will give an error on build when the interface is changed
Upvotes: 5
Views: 7697
Reputation: 117
Recommend: Don't use this package anymore
https://github.com/dsherret/ts-nameof/issues/121
Yes, this can be done in Javascript/Typescript. There is a typescript module.
Shamelessly copied from the manual.
nameof(console);
nameof(console.log);
nameof(console["warn"]);
Transforms to:
"console";
"log";
"warn";
There are more nice examples in the manual.
The solution for yours question:
interface IMyObject {
myPropertyOther: string;
}
let myObject: IMyObject = {
myProperty: 'Hello world'
};
console.log(myObject[nameof<IMyObject>((o) => o.myProperty)]);
Upvotes: 2
Reputation: 15886
I made a library that fetches the name of a property at runtime, even for types that don't exist at runtime (interfaces or types in TypeScript):
It can be found on NPM here: @fluffy-spoon/name-of
The source code is simple (just a few lines of code): https://github.com/ffMathy/FluffySpoon.JavaScript.NameOf
import { getPropertyName, getDeepPropertyName } from '@fluffy-spoon/name-of';
interface SomeType {
foo: boolean;
someNestedObject: {
bar: string;
}
}
console.log(getPropertyName<SomeType>(x => x.foo)); //prints "foo"
console.log(getPropertyName<SomeType>(x => x.someNestedObject)); //prints "someNestedObject"
console.log(getPropertyName<SomeType>(x => x.someNestedObject.bar)); //prints "bar"
console.log(getDeepPropertyName<SomeType>(x => x.foo)); //prints "foo"
console.log(getDeepPropertyName<SomeType>(x => x.someNestedObject)); //prints "someNestedObject"
console.log(getDeepPropertyName<SomeType>(x => x.someNestedObject.bar)); //prints "someNestedObject.bar"
In case you don't want to install the NPM package.
function getPropertyNameInternal<T = unknown>(expression: (instance: T) => any, options: {
isDeep: boolean
}) {
let propertyThatWasAccessed = "";
var proxy: any = new Proxy({} as any, {
get: function(_: any, prop: any) {
if(options.isDeep) {
if(propertyThatWasAccessed)
propertyThatWasAccessed += ".";
propertyThatWasAccessed += prop;
} else {
propertyThatWasAccessed = prop;
}
return proxy;
}
});
expression(proxy);
return propertyThatWasAccessed;
}
export function getPropertyName<T = unknown>(expression: (instance: T) => any) {
return getPropertyNameInternal(expression, {
isDeep: false
});
}
export function getDeepPropertyName<T = unknown>(expression: (instance: T) => any) {
return getPropertyNameInternal(expression, {
isDeep: true
});
}
Upvotes: 4
Reputation: 249476
There is no nameof
operator in Javascript/Typescript. You can creat a function that takes the key of another object and this is checked by the typescript compiler:
function keyOf<T>(o: T, k: keyof T) {
return k
}
let o = { a: 1 }
keyOf(o, 'a'); //ok
keyOf(o, 'b'); //err
Upvotes: 6