用打字稿动态调用粉笔
Dynamic call of chalk with typescript
我正在使用 typescript 并想动态调用 chalk 方法,请参阅我的代码:
import chalk from 'chalk';
const color: string = "red";
const message: string = "My Title";
const light: boolean = false;
const colorName = `bg${capitalize(color)}${light ? 'Bright' : ''}`;
console.log(chalk[colorName](message));
因此,颜色函数将消息背景的颜色作为一个值。消息是内容,灯光是布尔值,用于判断背景是否应该使用亮色版本。
问题是打字稿抛出这个错误:
Element implicitly has an 'any' type because expression of type 'any' can't be used to index type 'ChalkInstance'.
在 chalk[colorName]
部分。
我已经试过 (chalk[colorName] as keyof ChalkInstance)
。并且已经看过 (这基本上是同一个问题)。显然,回答的解决方案不适用于我的情况。
您需要做一些事情。
- 从变量
color
、message
和 light
中删除多余的显式类型。这样做不仅没有必要,而且实际上会干扰 TypeScript properly inferring the literal value of those types。换句话说,如果你定义 const color = "red";
TypeScript 会知道,因为它是一个 const
,它永远不会改变,它总是可以被视为字符串文字 "red"
而不是更多通用 string
。 (作为一般规则,你永远不应该显式定义 const
变量的类型。)
const color = "red";
const message = "My Title";
const light = false;
- 确保您的
capitalize()
函数正确定义了它的 return 类型。在这种情况下,实际上有一个awesome built-in utility type Capitalize<>
which you can use here。结合 TypeScript 泛型,您可以以 TypeScript 知道的方式定义函数,例如如果 "red"
是输入,"Red"
是输出。
function capitalize<S extends string>(c: S) {
return c.replace(/\b\w/g, firstLetter => firstLetter.toUpperCase()) as Capitalize<S>;
}
- Use the
as const
assertion 当您定义 colorName
(以及您可能需要定义的任何其他类似变量)时。如果不这样做,colorName
的类型将被推断为 string
,这不利于索引 chalk
。使用 as const
,您基本上是在告诉 TypeScript 将结果表达式视为 文字字符串值 。在这种情况下,colorName
的类型变为 "bgRedBright" | "bgRed"
,它们都是 chalk
. 的有效索引
const colorName = `bg${capitalize(color)}${light ? 'Bright' : ''}` as const;
^^^^^^^^
import chalk from 'chalk';
const color = "red";
const message = "My Title";
const light = false;
function capitalize<S extends string>(c: S) {
return c.replace(/\b\w/g, firstLetter => firstLetter.toUpperCase()) as Capitalize<S>;
}
const colorName = `bg${capitalize(color)}${light ? 'Bright' : ''}` as const;
console.log(chalk[colorName](message));
编辑:将来您可能需要以动态方式定义 color
变量,而不仅仅是硬编码文字 "red"
值。在这种情况下,您需要一种方法来满足 TypeScript color
将 总是 是有效的东西,因为我们刚刚设置的所有其他推理。
在这里,我们实际上确实想要为某些变量显式定义类型,特别是let
和函数参数。幸运的是,chalk
provides 是这种情况下非常有用的类型,ForegroundColor
基本上是所有有效的“基本”颜色,并且在放入时恰好与 BackgroundColor
兼容形式 `bg${ForegroundColor`
,这正是我们在这里需要的。
import chalk, { ForegroundColor } from 'chalk';
let color: ForegroundColor = "red";
color = "blue";
我们甚至可以通过更严格地控制参数的类型来改进 capitalize()
函数:
function capitalize<S extends ForegroundColor>(c: S) {
return c.replace(/\b\w/g, firstLetter => firstLetter.toUpperCase()) as Capitalize<S>;
}
Another playground example that puts those further improvements into practice.
我自己找到了问题的答案。问题是 colorName
变量的类型是 any
,chalk 无法将其识别为 chalk
class 的索引。这里 colorName
变量的值可以包含背景颜色的所有值,无论它们是否明亮。
然后我有两个解决方案:
- 对颜色的所有值进行硬编码(这会花费很长时间)
- 找到表示颜色的类型并显式设置为
colorName
变量的类型
我的解决方案与第二个想法很接近,但是,Chalk
库没有提供颜色类型。但是,我们可以导入所有 BackgroundColors
的显式列表。然后,我们只需要将这些关键词的类型指定为colorName
变量的类型即可。
import { BackgroundColor } from 'chalk';
import chalk from 'chalk';
const color: string = "red";
const message: string = "My Title";
const light: boolean = false;
const colorName = `bg${capitalize(color)}${light ? 'Bright' : ''}` as typeof BackgroundColor;
console.log(chalk[colorName](message));
PS:注意变量color
、message
和light
的类型是hard-coded。在应用程序上,这些值是动态的,这是一种更清晰的方式。
我正在使用 typescript 并想动态调用 chalk 方法,请参阅我的代码:
import chalk from 'chalk';
const color: string = "red";
const message: string = "My Title";
const light: boolean = false;
const colorName = `bg${capitalize(color)}${light ? 'Bright' : ''}`;
console.log(chalk[colorName](message));
因此,颜色函数将消息背景的颜色作为一个值。消息是内容,灯光是布尔值,用于判断背景是否应该使用亮色版本。
问题是打字稿抛出这个错误:
Element implicitly has an 'any' type because expression of type 'any' can't be used to index type 'ChalkInstance'.
在 chalk[colorName]
部分。
我已经试过 (chalk[colorName] as keyof ChalkInstance)
。并且已经看过
您需要做一些事情。
- 从变量
color
、message
和light
中删除多余的显式类型。这样做不仅没有必要,而且实际上会干扰 TypeScript properly inferring the literal value of those types。换句话说,如果你定义const color = "red";
TypeScript 会知道,因为它是一个const
,它永远不会改变,它总是可以被视为字符串文字"red"
而不是更多通用string
。 (作为一般规则,你永远不应该显式定义const
变量的类型。)
const color = "red";
const message = "My Title";
const light = false;
- 确保您的
capitalize()
函数正确定义了它的 return 类型。在这种情况下,实际上有一个awesome built-in utility typeCapitalize<>
which you can use here。结合 TypeScript 泛型,您可以以 TypeScript 知道的方式定义函数,例如如果"red"
是输入,"Red"
是输出。
function capitalize<S extends string>(c: S) {
return c.replace(/\b\w/g, firstLetter => firstLetter.toUpperCase()) as Capitalize<S>;
}
- Use the
as const
assertion 当您定义colorName
(以及您可能需要定义的任何其他类似变量)时。如果不这样做,colorName
的类型将被推断为string
,这不利于索引chalk
。使用as const
,您基本上是在告诉 TypeScript 将结果表达式视为 文字字符串值 。在这种情况下,colorName
的类型变为"bgRedBright" | "bgRed"
,它们都是chalk
. 的有效索引
const colorName = `bg${capitalize(color)}${light ? 'Bright' : ''}` as const;
^^^^^^^^
import chalk from 'chalk';
const color = "red";
const message = "My Title";
const light = false;
function capitalize<S extends string>(c: S) {
return c.replace(/\b\w/g, firstLetter => firstLetter.toUpperCase()) as Capitalize<S>;
}
const colorName = `bg${capitalize(color)}${light ? 'Bright' : ''}` as const;
console.log(chalk[colorName](message));
编辑:将来您可能需要以动态方式定义 color
变量,而不仅仅是硬编码文字 "red"
值。在这种情况下,您需要一种方法来满足 TypeScript color
将 总是 是有效的东西,因为我们刚刚设置的所有其他推理。
在这里,我们实际上确实想要为某些变量显式定义类型,特别是let
和函数参数。幸运的是,chalk
provides 是这种情况下非常有用的类型,ForegroundColor
基本上是所有有效的“基本”颜色,并且在放入时恰好与 BackgroundColor
兼容形式 `bg${ForegroundColor`
,这正是我们在这里需要的。
import chalk, { ForegroundColor } from 'chalk';
let color: ForegroundColor = "red";
color = "blue";
我们甚至可以通过更严格地控制参数的类型来改进 capitalize()
函数:
function capitalize<S extends ForegroundColor>(c: S) {
return c.replace(/\b\w/g, firstLetter => firstLetter.toUpperCase()) as Capitalize<S>;
}
Another playground example that puts those further improvements into practice.
我自己找到了问题的答案。问题是 colorName
变量的类型是 any
,chalk 无法将其识别为 chalk
class 的索引。这里 colorName
变量的值可以包含背景颜色的所有值,无论它们是否明亮。
然后我有两个解决方案:
- 对颜色的所有值进行硬编码(这会花费很长时间)
- 找到表示颜色的类型并显式设置为
colorName
变量的类型
我的解决方案与第二个想法很接近,但是,Chalk
库没有提供颜色类型。但是,我们可以导入所有 BackgroundColors
的显式列表。然后,我们只需要将这些关键词的类型指定为colorName
变量的类型即可。
import { BackgroundColor } from 'chalk';
import chalk from 'chalk';
const color: string = "red";
const message: string = "My Title";
const light: boolean = false;
const colorName = `bg${capitalize(color)}${light ? 'Bright' : ''}` as typeof BackgroundColor;
console.log(chalk[colorName](message));
PS:注意变量color
、message
和light
的类型是hard-coded。在应用程序上,这些值是动态的,这是一种更清晰的方式。