This code gives me "Type 'string' is not assignable to type 'never'" where the comment is made.
type serviceInfoType = {
PORT: number;
HOST: string;
MS_NAME: string;
MS_KEY: string;
};
type serviceInfoParametersType = keyof serviceInfoType;
let serviceInfo = {} as serviceInfoType;
let serviceInfoParameters: Array<serviceInfoParametersType> = [
"PORT",
"HOST",
"MS_NAME",
"MS_KEY",
];
serviceInfoParameters.forEach((e) => {
// Type 'string' is not assignable to type 'never'
serviceInfo[e] = 'something';
});
If I change the code to this:
serviceInfo[e as string] = 'something';
Then it works. But I have no idea why it doesn't work. Can anyone explain why it says type never?
EDIT:
Alex Kolarski made a right call of me trying to assign .env variables (which types I changed).
You can do this (which works and is correct way):
if (e === "PORT") serviceInfo[e] = process.env[e];
else if (e === "MICROSERVICE_NAME") serviceInfo[e] = process.env[e];
else serviceInfo[e] = process.env[e];
Which is "essentially" this:
serviceInfo[e] = process.env[e];
Except this doesn't work.
If you don't need anything else but to assign values you are OK with the 'as string' hack. But if you need to do other stuff like changing or checking types of the variables, you should use the correct way. Because then the intellisense works and TS is happy.
CodePudding user response:
The error happens because TypeScript does not know the type of serviceInfo[e]
.
If e
= "PORT" the type of serviceInfo[e]
is number
If e
= NOT "PORT" the type of serviceInfo[e]
is string
So the type of serviceInfo[e]
becomes never
since it cannot be both string
and number
at the same time.
So when you have serviceInfo[e] = 'something'
, TypeScript it is not sure how to type check it, because you are trying to assign a string
("something") to serviceInfo[e]
that can be either string
and number
and in the case if it is a number
there should be an error.
serviceInfo["PORT"] = 'something';
- you are assigning string
to a number
.
There are several ways to mitigate this.
Option 1:
Make sure serviceInfo[e]
is only one type the type in the forEach like so:
serviceInfoParameters.forEach((e) => {
if (e === "PORT") {
serviceInfo[e] = 3000;
} else {
serviceInfo[e] = 'something';
}
});
This way TypeScript will figure out that if e
is not "PORT"
it always defaults to a string.
Option 2 (not ideal): You can make everything in serviceInfoType a string like so:
type serviceInfoType = {
PORT: string;
HOST: string;
MS_NAME: string;
MS_KEY: string;
};
Then you will have no issues.
I'm not sure of the goal here, so I cannot provide more context, but it seems to me that you are trying to load .env file and in that case it make sense that everything should be a string and type it that way.
Then you can convert it if you need a number.