打字稿类型条件扩展对象
typescript type conditionals extends object
我想要有条件类型,即某物是一个对象。
type Id = {
id: number
obj: {
x: 5
}
}
type ObjString<T> = {
[P in keyof T]:
T[P] extends Object ? string : T[P]
}
const f: ObjString<Id> = {
id: 4,
obj: "xxxx"
}
这里,obj
属性 正确映射到 f
对象中的字符串,但是对于 id
属性,我会得到此错误消息:
error TS2322: Type 'number' is not assignable to type 'string'.
这意味着 T[P] extends Object
对于 number
的计算结果为真。我应该如何构造条件,以便 number 的计算结果为 false,而 object 的计算结果为 true?
这是因为Object
类型太笼统了。 javascript 中的每个原始值都扩展了 Object
,因为即使是数字和字符串也有自己的方法。
考虑这个例子:
type Check1 = string extends Object ? true : false // true
type Check2 = number extends Object ? true : false // true
我觉得换个角度解决问题比较好。您可以检查类型是否为原始类型:
type Id = {
id: number
obj: {
x: 5
}
}
type Primitives = string | number | boolean | bigint | symbol;
type ObjString<T> = {
[P in keyof T]:
T[P] extends Primitives ? T[P] : string
}
const f: ObjString<Id> = {
id: 4,
obj: "xxxx"
}
Object
类型并不真正对应于 TypeScript 中的非基元;相反,它是可以像对象一样被索引到的值的类型。这包括像 string
和 number
这样的基元,它们得到 wrapped with objects when you index into them (and thus supports things like "hello".toUpperCase()
and (123).toFixed(2)
). Only null
and undefined
are not Object
s in this sense. Object
in TypeScript is rarely what you want.
如果你想在 TypeScript 中找到一个意味着“非原始”的类型,你可以使用 the object
type 代替(以小写 o
开头而不是大写 O
):
type ObjString<T> = {
[P in keyof T]:
T[P] extends object ? string : T[P]
}
type Z = ObjString<Id>;
/* type Z = {
id: number;
obj: string;
} */
const f: ObjString<Id> = {
id: 4,
obj: "xxxx"
}
然后一切都按照你想要的方式进行。
请记住,数组和函数也是 object
,因此您可能会遇到一些不良行为,具体取决于您想在那里看到的内容:
type Hmm = ObjString<{ foo(): string, bar: number[] }>;
// type Hmm = { foo: string; bar: string; }
我想要有条件类型,即某物是一个对象。
type Id = {
id: number
obj: {
x: 5
}
}
type ObjString<T> = {
[P in keyof T]:
T[P] extends Object ? string : T[P]
}
const f: ObjString<Id> = {
id: 4,
obj: "xxxx"
}
这里,obj
属性 正确映射到 f
对象中的字符串,但是对于 id
属性,我会得到此错误消息:
error TS2322: Type 'number' is not assignable to type 'string'.
这意味着 T[P] extends Object
对于 number
的计算结果为真。我应该如何构造条件,以便 number 的计算结果为 false,而 object 的计算结果为 true?
这是因为Object
类型太笼统了。 javascript 中的每个原始值都扩展了 Object
,因为即使是数字和字符串也有自己的方法。
考虑这个例子:
type Check1 = string extends Object ? true : false // true
type Check2 = number extends Object ? true : false // true
我觉得换个角度解决问题比较好。您可以检查类型是否为原始类型:
type Id = {
id: number
obj: {
x: 5
}
}
type Primitives = string | number | boolean | bigint | symbol;
type ObjString<T> = {
[P in keyof T]:
T[P] extends Primitives ? T[P] : string
}
const f: ObjString<Id> = {
id: 4,
obj: "xxxx"
}
Object
类型并不真正对应于 TypeScript 中的非基元;相反,它是可以像对象一样被索引到的值的类型。这包括像 string
和 number
这样的基元,它们得到 wrapped with objects when you index into them (and thus supports things like "hello".toUpperCase()
and (123).toFixed(2)
). Only null
and undefined
are not Object
s in this sense. Object
in TypeScript is rarely what you want.
如果你想在 TypeScript 中找到一个意味着“非原始”的类型,你可以使用 the object
type 代替(以小写 o
开头而不是大写 O
):
type ObjString<T> = {
[P in keyof T]:
T[P] extends object ? string : T[P]
}
type Z = ObjString<Id>;
/* type Z = {
id: number;
obj: string;
} */
const f: ObjString<Id> = {
id: 4,
obj: "xxxx"
}
然后一切都按照你想要的方式进行。
请记住,数组和函数也是 object
,因此您可能会遇到一些不良行为,具体取决于您想在那里看到的内容:
type Hmm = ObjString<{ foo(): string, bar: number[] }>;
// type Hmm = { foo: string; bar: string; }