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

Recommend: Don't use this package #121

Open
dsherret opened this issue Dec 18, 2021 · 16 comments
Open

Recommend: Don't use this package #121

dsherret opened this issue Dec 18, 2021 · 16 comments

Comments

@dsherret
Copy link
Owner

dsherret commented Dec 18, 2021

I now recommend not using this package or any other compiler transforms. It's neat, but it creates code that is not portable and makes it hard to switch to new build systems. The current solutions for injecting compiler transforms are hacky and I can't imagine the TS compiler ever supporting this out of the box.

I personally now just use the following function. It's simple and it works for most cases... of course it's not as featureful, but it gets you 90% of the way there.

export function nameof<TObject>(obj: TObject, key: keyof TObject): string;
export function nameof<TObject>(key: keyof TObject): string;
export function nameof(key1: any, key2?: any): any {
  return key2 ?? key1;
}

Example Use

import { nameof } from "./some-relative-import";

interface SomeInterface {
  someProperty: number;
}

// with types
console.log(nameof<SomeInterface>("someProperty")); // "someProperty"

// with values
const myVar: SomeInterface = { someProperty: 5 };
console.log(nameof(myVar, "someProperty")); // "someProperty"
@dsherret dsherret pinned this issue Dec 18, 2021
@dobromyslov
Copy link

Thank you for your candor. It would be awesome if you also write a note to this answer https://stackoverflow.com/a/33556815/1177597 when you have spare time.

@PKnight-CheckWriters
Copy link

Can you show how it should be used?

@dsherret
Copy link
Owner Author

dsherret commented Jan 9, 2022

@PKnight-CheckWriters I updated the main post to show some examples.

@sotnikov-link
Copy link

I published package ts-keyof. Maybe it will be useful for someone. Thanks for ts-nameof! I used it about 3 years, but now I need use esbuild and swc.

@wh1t3cAt1k
Copy link

wh1t3cAt1k commented May 12, 2022

@dsherret I'm on the fence about your recommendation... When one uses the keyof approach it's not automatically caught by VSCode refactoring tracking mechanism, and you get tons of compilation errors when renaming the keys.

If this issue was addressed by the VSCode team, I would probably try and make the switch.

@PinkChampagne17
Copy link

@wh1t3cAt1k I published package ts-nameof-proxy, referenced properties can be renamed by VS Code and you can try to use it.

@sotnikov-link
Copy link

@wh1t3cAt1k If for you enough ts-keyof then you can disable useAliasesForRenames in VSCode: microsoft/TypeScript#29238 (comment)

Screen-Recording-2022-07-28-at-09 02 48

I declined rename for interface property in my lib, because it doesn't work with TypeScript Refactoring correctly: sotnikov-link/ts-keyof#1

@wh1t3cAt1k
Copy link

wh1t3cAt1k commented Jul 28, 2022

@dsherret @sotnikov-link

If I am understanding it right, there is still one important consideration that still makes this library not deserving of deprecation.

When using ts-nameof, import type is often enough, which disappears completely at compile time, has no import side effects.

With runtime-based libraries, you need to actually import the whole dependency tree of the entity to "nameof", potentially introducing a build/runtime slowdown and even introducing circular dependencies.

I'm not completely persuaded that having no pre-processing steps is a big win. To me, it was never a hassle to set up a simple babel macro.

If there is a goal to transfer to swc, it might expose some extensibility too?

@benjamin-rood
Copy link

@dsherret Thanks for being transparent about the state of this package, it's much appreciated. Can you show me how I would go about implementing nameof.full, though? I see the full function defined in the exported namespace(s), but I don't see any function implementation in any typescript files... 🤔

@thexpand
Copy link

There's still no way to get the name of the interface itself as a string, though.

@celluj34
Copy link

How can I use this simplified method for variables without a parent object?

Something like

export function get_some_info(
  date: string | number,
  ...etc
) {
  if (!date) {
    console.log(`${nameof(date)} is required!`);
    return;
  }

  // ...etc
}

@manuth
Copy link

manuth commented Mar 7, 2023

@dsherret Thanks for being transparent about the state of this package, it's much appreciated. Can you show me how I would go about implementing nameof.full, though? I see the full function defined in the exported namespace(s), but I don't see any function implementation in any typescript files... thinking

I know this is quite a late answer but just for clarification:
You not finding a definition of nameof.full is because nameof.full doesn't run any code.

ts-nameof hooks into your compiler program (ttypescript, ts-patch or babel for example), finds all function calls to functions called nameof, nameof.full, nameof.split etc. and replaces them with the desired result.

So there is no drop-in replacement of ts-nameof. All we can do is wait and hope for typescript to implement it at some point.

@manuth
Copy link

manuth commented Mar 7, 2023

How can I use this simplified method for variables without a parent object?

@celluj34 I think the package written by @sotnikov-link will help you.
You'd have to change your code to something like this:

import { keyof } from "ts-keyof";

export function get_some_info(
  date: string | number,
  ...etc
) {
  if (!date) {
    console.log(`${keyof({ date })} is required!`);
    return;
  }

  // ...etc

@longlostbro
Copy link

I now recommend not using this package or any other compiler transforms. It's neat, but it creates code that is not portable and makes it hard to switch to new build systems. The current solutions for injecting compiler transforms are hacky and I can't imagine the TS compiler ever supporting this out of the box.

I personally now just use the following function. It's simple and it works for most cases... of course it's not as featureful, but it gets you 90% of the way there.

export function nameof<TObject>(obj: TObject, key: keyof TObject): string;
export function nameof<TObject>(key: keyof TObject): string;
export function nameof(key1: any, key2?: any): any {
  return key2 ?? key1;
}

Example Use

import { nameof } from "./some-relative-import";

interface SomeInterface {
  someProperty: number;
}

// with types
console.log(nameof<SomeInterface>("someProperty")); // "someProperty"

// with values
const myVar: SomeInterface = { someProperty: 5 };
console.log(nameof(myVar, "someProperty")); // "someProperty"

Could we get some more explanation on why this is no longer recommended? It seems to me, if your environment is controllable, then the pros outway the cons.

@manuth
Copy link

manuth commented Aug 28, 2023

Hello everyone
I know it's been a lot of time but I just wanted to note that only recently I indeed did publish a drop-in replacement for ts-nameof.

All you have to do is remove the @types/ts-nameof and ts-nameof packages and instead install my new "TypeScript nameof" project as described in the project's README.

Feel free to check it out:
https://github.com/typescript-nameof/nameof

@ShuuyaMonzen
Copy link

ShuuyaMonzen commented Jul 25, 2024

improved simple solution

export function nameof<TObject>(obj: TObject, key: keyof TObject): string;
export function nameof<TObject>(key: keyof TObject): string;
export function nameof<TObject>(type: { new(...args: any[]): TObject }): string;
export function nameof(key1: any, key2?: any): any {
  if(typeof(key1) == 'function' && key1.name){
    return key1.name;
  }
  return key2 ?? key1;
}

add example

class User {}
nameof(User) → 'User'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests