TypeScript does not currently have the capacity to do exactly what you're asking for:
You want the compiler to treat process.env.REACT_APP_ENV as some "unknown but unique" string literal, much the way that unique symbol works for symbol-typed values. There was an experimental pull request at microsoft/TypeScript#33038 which would have allowed things like unique string, but it never made it into the language.
Moreover, you need to be able to concatenate that unique string to other string literals and have some sort of unique output; maybe this would also require supporting unique string inside "pattern" template literal types as implemented in microsoft/TypeScript#40598, and it isn't obvious that this would work.
And even if that were all taken care of, you currently can't use pattern template literal types as object keys; see microsoft/TypeScript#42192. An object type like Record<`foo${string}`, number> is unfortunately treated very much like {}; it will not complain if you assign a type like {fooOops: "This is not a number"} to it. ( Well, at least this part is fixed for TS4.4; pattern template literals can be used in index signatures as per microsoft/TypeScript#44512 )
All of that put together means this is just not within the realm of possibility for TypeScript as of TS 4.4.
Instead you would need some sort of workaround. I was toying around with using a string enum to simulate an opaque/nominal subtype of string that works with keys, but it doesn't really do anything more useful than the workaround I settled on: a placeholder string literal type like "###${process.env.REACT_APP_ENV}###" that we pretend is the known actual type of process.env.REACT_APP_ENV. As long as we only refer to the type as process.env.REACT_APP_ENV and not as the pretend string literal, everything will work out. We might even want the pretend value to be something like "!!!PLACEHOLDER_DO_NOT_USE_THIS!!!" or whatever you need to convince people not to use the literal type.
It would look like this:
declare const process: {
env: {// the following type is a fiction but is the best I can do
REACT_APP_ENV: "###${process.env.REACT_APP_ENV}###"
}
}
And then your claimKey would be a const-asserted template string so that the compiler can concatenate it and maintain the string-literal-ness of it:
const claimKey = `urn:${process.env.REACT_APP_ENV}:claims/user-id` as const
And everything works as desired, mostly:
interface MyInterface {
email: string;
[claimKey]: string;
}
const myInterface: MyInterface = {
email: "[email protected]",
[claimKey]: "123"
}
Hooray! Still, it's just a workaround. That placeholder value will likely show up as IntelliSense hints, unfortunately:
const booIntelliSense: MyInterface = {
email: "",
"urn:###${process.env.REACT_APP_ENV}###:claims/user-id": "oops" // <-- hinted by IntelliSense!
}
so it's really not perfect. Oh well.
Playground link to code
myTypedefinition isn’t valid TypeScript or JavaScript. Could you edit the code here to be a minimal reproducible example?string" in a way that works with concatenation and doesn't have other side effects. A workaround like this might suffice? If so, I'll write up an answer. (Please also edit the text of the question so that it's a minimal reproducible example without needing to click a link that brings you outside of Stack Overflow.)