英文:
Typescript returns unknown for generic only on undefined input
问题
我正在尝试编写一个通用的环境字段获取函数,目前有以下代码:
```js
export interface Config {
readonly PORT: number;
readonly DATABASE_URL: string;
// ... other fields
}
const config: Config = Object.freeze({
ENVIRONMENT,
PROJECT_NAME,
PORT: parseInt(getEnvVariable('PORT', '9000'), 10),
DATABASE_URL: getEnvVariable('DATABASE_URL'),
AWS_REGION,
});
function getEnvVariable<T>(name: string, defaultValue?: T): T | string {
const val = process.env[name];
if (val) {
return val;
}
if (defaultValue) {
return defaultValue;
}
throw new Error(`Missing environment variable: ${name}`);
}
我目前遇到的错误是:
Type 'Readonly<{ ENVIRONMENT: string; PROJECT_NAME: string; PORT: number; DATABASE_URL: unknown; AWS_REGION: string; }>' is not assignable to type 'Config'.
Types of property 'DATABASE_URL' are incompatible.
Type 'unknown' is not assignable to type 'string'.
出现这个错误的原因是,如果我的 defaultValue
输入为 undefined
,它会导致这个错误,即使我进行了真值检查。
如何在不使用 ''
作为 defaultValue
的情况下解决这个问题?
<details>
<summary>英文:</summary>
I'm trying to write a generic env field getter function and currently have this:
```js
export interface Config {
readonly PORT: number;
readonly DATABASE_URL: string;
// ... other fields
}
const config: Config = Object.freeze({
ENVIRONMENT,
PROJECT_NAME,
PORT: parseInt(getEnvVariable('PORT', '9000'), 10),
DATABASE_URL: getEnvVariable('DATABASE_URL'),
AWS_REGION,
});
function getEnvVariable<T>(name: string, defaultValue?: T): T | string {
const val = process.env[name];
if (val) {
return val;
}
if (defaultValue) {
return defaultValue;
}
throw new Error(`Missing environment variable: ${name}`);
}
and I'm currently getting the error:
Type 'Readonly<{ ENVIRONMENT: string; PROJECT_NAME: string; PORT: number; DATABASE_URL: unknown; AWS_REGION: string; }>' is not assignable to type 'Config'.
Types of property 'DATABASE_URL' are incompatible.
Type 'unknown' is not assignable to type 'string'.
For some reason if my defaultValue
input is undefined
, it will give this error, even though I do a truthy check.
How would I fix this without using an ''
as the defaultValue
?
答案1
得分: 0
如果您不向 getEnvVariable
函数传递 defaultValue
参数,那么编译器将无法为泛型类型参数 T
推断出推断位置。因此,推断会失败,T
会回退到其约束,它隐式地是未知类型。
如果您希望 T
在没有提供 defaultValue
时回退到其他值,您可以使用默认类型参数,如下所示:
function getEnvVariable<T = string>(
// 默认类型参数 ----> ^^^^^^^^
name: string, defaultValue?: T
): T | string { /* 实现 */ }
然后,当未提供 defaultValue
时,您将获得所期望的行为:
const unsuppliedDefault = getEnvVariable("Y");
// const unsuppliedDefault: string
而当提供了 defaultValue
时,行为不会改变:
const suppliedDefault = getEnvVariable("X", Math.random());
// const suppliedDefault: string | number
英文:
If you don't pass in a defaultValue
argument to getEnvVariable
, then the compiler has no inference site for the generic type parameter T
. So inference fails, and T
falls back to its constraint, which is implicitly the unknown
type.
If you'd like T
to fall back to something else, you can use a default type argument as shown here:
function getEnvVariable<T = string>(
// default type arg ----> ^^^^^^^^
name: string, defaultValue?: T
): T | string { /* impl */ }
Then you'll get the desired behavior when defaultValue
isn't supplied:
const unsuppliedDefault = getEnvVariable("Y");
// const unsuppliedDefault: string
without changing the behavior when it is:
const suppliedDefault = getEnvVariable("X", Math.random());
// const suppliedDefault: string | number
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论