我想创建一个 TypeScript 类型来检查元素是否可以是字符串。
这意味着该元素可以具有“string”或“any”类型,但不能具有“number”、“boolean”、“number[]”、“Person”等类型。
我尝试使用条件类型,但我找不到如何排除“所有不可能是字符串的”。
我也尝试了排除类型
编辑
我更好地解释了我的问题:我创建了一个静态方法
foo(data)
,如果数据是string
,它将执行某些操作并返回string
,或者执行其他操作,如果数据不是number
,则返回string
.
为此,很简单,我可以像这样进行重载:
class FooClass {
static foo(data: string): string
static foo(data: any): number
static foo(data: any): string | number {
if (typeof data === 'string') {
return 'a';
} else {
return 2;
}
}
}
现在,假设如果
foo()
不是 data
,则 string
方法将抛出错误。我有两个案例:
如果该方法的用户不知道数据的类型(可能是
string
),我希望他可以使用此方法,如果不是string
,我将返回错误。
如果用户知道数据的类型(例如,
number
),我想告诉他这是不可能的,它不可能是string
。我想告诉大家的是,这是在类型检查时进行的(IDE 中显示的错误),而不是在运行时进行。
class FooClass {
static foo(data: string): string
static foo(data: NotAString): Error
static foo(data: any): string | Error {
if (typeof data === 'string') {
return 'a';
} else {
return new Error();
}
}
}
let foo1: string;
const bar1: string = FooClass.foo(foo1); // No error
let foo2: any;
const bar2: string = FooClass.foo(foo2); // No error
let foo3: number;
const bar3: string = FooClass.foo(foo3); // Error (displayed on the IDE)
let foo4: Bar;
const bar4: string = FooClass.foo(foo4); // Error (displayed on the IDE)
我想知道如何定义类型 NotAString(或其相反的 CouldBeAString)。
有什么想法吗?
谢谢!
您似乎将类型系统与功能检查混淆了。
如果您需要在运行时检查某些内容是否是字符串,您将使用与普通 JS 中相同的逻辑。
运行时检查属性
if (typeof something === 'string') { ... }
如果我们谈论的是从 API 或类似的东西获取的数据,你总是需要使用这样的东西,因为类型系统不会为你进行自动运行时检查。
条件型疏化
如果您需要创建一个条件类型来允许您对参数进行类型细化,有几种方法可以实现。不过,这里需要注意的一件事是:
unknown
是当前版本TS中的默认类型,而不是any
unknown
和 any
表示该语言中的任何有效数据类型。你不能说某件事是 unknown
但不能说 number
或 boolean
。unknown
Record<string, unknown>
对于类型细化,您可以使用泛型属性和 extends 关键字的组合。
type Result<T> = T extends string
? A
: T extends boolean
? B
: T extends number
? C
: never;
其中A、B、C是基于泛型类型的结果类型。
如果没有显式设置泛型参数,则传入的 prop 默认为
unknown
类型。您还可以将其范围限制为输入参数可以包含的几个值,以进行更精细的控制。
NotAString
很简单:
type NotAString = number | boolean | symbol | bigint | null | undefined | object
另一方面,定义
CouldBeAString
的唯一方法是使用类型参数:
type CouldBeAString<S, R = S> = string extends S ? R : S extends string ? R : never
现在你可以做:
function foo<S>(data: CouldBeAString<S>) { ... }
foo(1) // Error!
foo(1 as string | number) // works
foo(1 as unknown) // works
foo(1 as '1' | 1) // works
foo('1') // works