首页 > 解决方案 > 类型字符串不可分配给字符串文字

问题描述

我想使用来自typescript. 我的界面:

interface Props {
   size: 'small' | 'medium' | 'large';
   count: number;
}

但是我遇到了两个问题:

  1. 使用破坏时出错

如果我在对象中有我的数据

const data = {
  size: 'small',
  count: 36,
};

然后当试图解构它时,<Component {...data}>我得到以下错误:

Type 'string' is not assignable to type '"small" | "medium" | "large"'
  1. 使用环境变量

我使用环境变量得到完全相同的错误:

size = process.env.SIZE; // while having SIZE = 'small'; in my .env file

有人可以帮助我就如何修复这些问题提供建议吗?高度赞赏。

标签: typescript

解决方案


前言:我会为联合定义一个类型别名,所以你可以在多个地方使用它:

type Size = "small" | "medium" | "large";

用那个名字...

回复 #1:问题在于,尽管您已用作"small"的值data.size,但它可以被任何其他字符串覆盖。它的类型是string,而不是Size( "small" | "medium" | "large")。"small" | "medium" | "large"但是,您可以通过为对象定义类型并将其应用于data常量来告诉 TypeScript 它是:

// Inline, or use `type` to define it separately
const data: Props  = {
//          ^^^^^
  size: 'small',
  count: 36, // I've assumed the `number: 36` in the question is a typo
};

...或通过类型断言:

const data  = {
  size: "small" as Size,
//             ^^^^^^^^
  count: 36,
};

或者,如果data永远不会改变,你可以as const这样说:

const data  = {
  size: "small",
  count: 36,
} as const;
//^^^^^^^^

关于#2,环境变量可以是任何东西,所以通常你会使用类型断言函数:

function assertValidSize(size: string): size is Size {
    switch (size) {
        case "small":
        case "medium":
        case "large":
            return;
        default:
            throw new Error(`Invalid 'Size' value "${size}"`);
    }
}

然后:

const envSize = process.env.SIZE;
assertValidSize(envSize);
data.size = envSize;

有几种方法可以旋转它(类型保护函数而不是断言函数等),但这是基本思想。


在您问过的评论中:

是否可以在不手动查看案例的情况下为环境变量创建断言功能?就像从类型本身中获取值并循环遍历它们?

如果您从类型开始,则不是,而是可以从有效大小的常量数组开始,然后基于该常量数组派生类型和类型断言函数(和/或类型保护函数):

// The valid sizes
const sizes = ["small", "medium", "large"] as const;

// The type for an entry in `sizes`
type Size = typeof sizes[number]; // Ends up being `"small" | "medium" | "large"

// A type assertion function for a valid size
function assertValidSize(size: string): asserts size is Size {
    if (!(sizes as [string, string, string]).includes(size)) {
        throw new Error(`Invalid Size value "${size}"`);
    }
}

// Using it with `process.env.SIZE`:
assertValidSize(process.env.SIZE);
let size: Size = process.env.SIZE;

as conston告诉 TypeScript 它的sizes内容不会改变,这让 TypeScript

游乐场链接


推荐阅读