dsherret / ts-nameof

nameof in TypeScript

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[Feature Request] Provide an index at runtime.

matthewbpt opened this issue · comments

I would like to be able to provide an array index at runtime rather than it be statically compiled.

type a = {
  b: {
    c: Array<{ d: string }>;
  };
};

const index = 1;

console.log('test nameof with array', nameof.full<a>(a => a.b.c[index].d));

This outputs 'b.c[index].d', but It would be amazing if it could output `b.c[${index}].d` instead, this is especially useful for providing paths for elements in Formik forms where the index will be dynamic. The workaround right now is to do something like:

nameof.full<a>(a => a.b.c[index].d)).replace(nameof(index), index)

Hey @matthewbpt, I've been thinking about this. Some concerns:

  1. This would be a breaking change.
  2. What if someone wants it to return "b.c[index].d"?
  3. Is this behaviour people would expect?

So to tackle these concerns and entertain the idea:

  1. I doubt many people are using element access expressions with nameof like this. They could be though and this being a breaking change is a major concern.
  2. If they want the previous behaviour they could do: nameof.full<a>(a => a.b.c[nameof(index)].d)
  3. I don't think people would expect this, but is making what's in the element a string useful when it's not a literal?

An opt-in approach might be:

// problem: would cause type errors when index type was number (like probably this one)
nameof.full<a>(a => a.b.c[`${index}`].d);

// problem: kind of long
nameof.full<a>(a => a.b.c[nameof.interpolate(index)].d);

nameof.interpolate?

I'm thinking this should be implemented as something like nameof.interpolate? (Better name?)

nameof.full<a>(a => a.b.c[nameof.interpolate(index)].d);
// goes to:
`b.c[${index}].d`;
  1. This would be a property of nameof so that it wouldn't need to add another global name (ex. adding a global interpolate function would not be nice).
  2. Function signature would be nameof.interpolate<T>(value: T): T; so that type errors wouldn't occur.

Pros:

  1. Not a breaking change.
  2. Opt-in. No surprise behaviour.

Cons:

  1. Long name.

Thoughts?

Hi @dsherret, I think nameof.interpolate is a great idea! Makes the intention very clear I think and prevents breaking changes.

I just need to update definitely typed, do a new release, and then this will be supported.

Ok. This is merged into definitely typed now. A new @types/ts-nameof package should be available very soon so closing this.