0
const func = <T extends object, S extends keyof PickByValue<T, string>>(
  obj: T,
  key: S
): string => {
  return obj[key];
};

PickByValue extracts the properties of T whose values are of type string.

type T = {
  propStr: string;
  propNum: number;
}
type Bar = PickByValue<T, string>;
// Bar = {
//   propStr: string;
// }

Is it possible to create a PickByValue such that the above code does not result in an error?

What we want to do is to use a property of type string within obj in a function.

islandryu
  • 41
  • 3
  • What is `PickByValue`? – md2perpe Feb 09 '22 at 16:31
  • @md2perpe I didn't explain it well enough.I have corrected the question. – islandryu Feb 09 '22 at 16:37
  • 1
    Looks like an XY problem to me. No matter how you write `PickByValue`, the compiler cannot usefully validate that `T[PickByValue]` is assignable to `string` if it doesn't know anything about `T` (except for the trivial solution that `PickByValue` produces `never` for all inputs). See https://github.com/microsoft/TypeScript/issues/30728. – jcalz Feb 09 '22 at 18:56
  • As you've asked it, then, the question has just "no, sorry" as an answer. Perhaps you'd like to reword the question so that it asks how to solve your underlying problem instead of proposing a non-working solution? In any case, a [mre] would be useful so others can play along at home without needing to guess at what `PickByValue` is and where it came from ([I happen to know where this came from](https://stackoverflow.com/questions/55150760/how-to-write-pickbyvalue-type), but the question should be self-contained). Good luck! – jcalz Feb 09 '22 at 18:57
  • @jcalz Thank you very much. I needed to know if it was possible, so my problem was solved! Looking at the issues on github, it looks like it will not be implemented in typescript in the future... – islandryu Feb 10 '22 at 03:45

1 Answers1

0

May 6th - TypeScript 4.6.2

You can do this by a generic constraint referencing T:

const func = <T extends PickByValue<T, string>, S extends keyof PickByValue<T, string>>(
  obj: T,
  key: S
): string => {
  return obj[key];
};

This is similar in behaviour to this question.

And when you call it, it works fine:

const obj = {
    foo: 0,
    bar: "",
    baz: "",
    quz: false,
};

// no errors
func(obj, "bar"); // intellisense for the keys that point to strings

Playground

kelsny
  • 23,009
  • 3
  • 19
  • 48