如下代码:
type K = "foo" | "bar";
interface SomeType {
[prop: K]: any;
}
给出此错误信息:
An index signature parameter type cannot be a union type. Consider using a mapped object type instead.
没人知道映射对象的类型是什么,所以让我们对其进行快速修复:
extends
子句,则与所有extends
子句相交没人知道映射对象的类型是什么,所以让我们对其进行快速修复:
+1,刚来到这里是因为我希望2.9支持您的示例代码将联合作为索引签名。 我认为这是人们长期以来想要的功能:#5683,#16760等。
你可以这样做:
type Foo = 'a' | 'b';
type Bar = {[key in Foo]: any};
尽管Bar
没有索引签名(即您不能再执行(obj as Bar)[value as Foo]
)。
编辑:虽然如果您可以使警告无效,我将永远感激不已!
我想从事这个:laughing:
将其他成员移动到与交集类型组合在一起的单独对象类型
如果包含对象类型是类,该怎么办?
我只能想象这是一个接口
所以在quickfix之后应该遵循什么代码?
type K = "1" | "2"
class SomeType {
a = 1;
[prop: K]: any;
}
所以在quickfix之后应该遵循什么代码?
我会说这不应该解决。
@mhegazy我正在使用3.0.0-rc,仍然收到与最初发布的错误相同的错误。 这是预期的吗?
我正在使用3.0.0-rc,仍然收到与最初发布的相同的错误。 这是预期的吗?
是。 错误是正确的。 该问题正在跟踪添加快速修复程序,即错误消息旁边的浅浆。
2.9.1和vscode没有可用的代码操作
@ThaJay我们不会向后移植此功能,请尝试设置较新的版本。
明显。 我很抱歉没有首先检查时间表,只是假设它足够新。 ts的新手。 将检查版本3。
如何形容:
function createRequestTypes(base){
return ['REQUEST', 'SUCCESS', 'FAILURE'].reduce((acc, type) => {
acc[type] = `${base}_${type}`
return acc
}, {})
}
const user = createRequestTypes('USER')
console.log(user.REQUEST) // error
// just string? like:
interface IRequestType: {[key: string]: string}
我在下面尝试过,都失败了:
type requestStatus = 'REQUEST' | 'SUCCESS' | 'FAILURE'
type requestTypes = {
[key in requestStatus]: string
}
// or
interface IRequestTypes {[key: keyType]: string}
// or even
type requestTypes = {
FAILURE: string,
SUCCESS: string,
REQUEST: string
}
@maicWorkGithub ,您可以在这里:
const user = createRequestTypes('USER')
console.log(user.REQUEST)
function createRequestTypes(base:string):requestTypes {
const result : requestTypes = {}
const arr : requestStatus[] = ['REQUEST', 'SUCCESS', 'FAILURE']
return arr.reduce((acc, type) => {
acc[type] = `${base}_${type}`
return acc
}, result)
}
type requestStatus = 'REQUEST' | 'SUCCESS' | 'FAILURE'
type requestTypes = { [key in requestStatus]?: string }
@ihorskyi谢谢!
只是好奇为什么type
有效,但是interface
无效。 有人可以解释一下吗? 限制(或功能) interface
的原因是什么?
type Foo = 'a' | 'b';
type Bar = {[key in Foo]: any}; // ok
interface Baz {[key in Foo]: any} // =>
// A computed property name in an interface must refer to an expression whose type is a literal type or a 'unique symbol' type.ts(1169)
// A computed property name must be of type 'string', 'number', 'symbol', or 'any'.ts(2464)
// 'Foo' only refers to a type, but is being used as a value here.ts(2693)
这是一个令人惊奇的自动修复程序。 感谢您实施! :)
类相同。
你可以这样做:
type Foo = 'a' | 'b'; type Bar = {[key in Foo]: any};
尽管
Bar
没有索引签名(即您不能再执行(obj as Bar)[value as Foo]
)。编辑:虽然如果您可以使警告无效,我将永远感激不已!
请改用Record
!
type Foo = 'a' | 'b'
type Bar = Record<Foo, any>
要使用类再添加一个示例...
class Foo {
a: string;
b: string;
}
type Bar = {[key in keyof Foo]: any};
使用Partial更好
type A = 'x' | 'y' | 'z';
type M = Partial<{
[key in A]: boolean
}>;
没人知道映射对象的类型是什么,所以让我们对其进行快速修复:
@DanielRosenwasser
为什么错误消息不能给出答案,例如显示一个使用映射类型的快速示例-只能是几行代码,与Typescript错误消息的平均长度一致:trollface:
有谁知道是否可以说使用类型或枚举作为键的接口只能接受一个属性?
例如这样的签名: { <field>: { <and|or|xor>: <int> } }
来自mongo bitwise运算符。
export enum BitwiseOperator {
and = "and",
or = "or",
xor = "xor",
}
export type BitwiseCondition = {
[key in BitwiseOperator]?: number;
}
然后使用它时,我想验证由接口定义的变量是否只有一个属性。
const query: BitwiseCondition = {
and: 5,
or: 6 // raise a ts error
};
@ b4dnewz您不能在Typescript中执行此操作。 解决方法: https :
@ b4dnewz ,如果您只想要1个属性,为什么不这样做呢?
export enum BitwiseOperator {
and = "and",
or = "or",
xor = "xor",
}
export type BitwiseCondition = {
operator: BitwiseOperator;
value: number;
}
@benwinding不幸的是,返回的形状与mongodb期望的形状不同
@apieceofbart感谢您的建议,我已经研究了它,在接口方面有点多余,但是可以正常工作,我不确定现在是否要实现它,因为如果最终用户尝试有两个运算符的按位条件,无论如何mongo都会引发错误
我试图使mongo-operators的定义尽可能简单,以避免我头疼headache也许将来会添加适当的支持
@ b4dnewz足够公平,
也许您可以使用的更简单的选择是:
export type BitwiseCondition =
| { or: number }
| { xor: number }
| { and: number }
这是您无需过多重复就可以获得的最接近的结果
@ b4dnewz足够公平,
也许您可以使用的更简单的选择是:
export type BitwiseCondition = | { or: number } | { xor: number } | { and: number }
这是您无需过多重复就可以获得的最接近的结果
在此示例中,这不会产生错误:
const query: BitwiseCondition = {
and: 5,
or: 6 // raise a ts error
};
我以为这就是重点
@apieceofbart ,
在此示例中,这不会产生错误:
export type BitwiseCondition =
| { or: number }
| { xor: number }
| { and: number }
const query: BitwiseCondition = {
and: 5,
or: 6 // doesn't raise a ts error!
};
哇! 太奇怪了:open_mouth:我不知道!
看来Typescript不支持对象的互斥类型。 这也是该语言的建议: https :
从这个stackoverflow答案中,可以使用条件类型(最难的类型)来实现这一点,但是它还不错。
/*
XOR boiler plate
*/
type Without<T, U> = { [P in Exclude<keyof T, keyof U>]?: never };
type XOR<T, U> = T | U extends object
? (Without<T, U> & U) | (Without<U, T> & T)
: T | U;
type XOR3<S, T, U> = XOR<S, XOR<T, U>>;
// Code start
export type BitwiseCondition = XOR3<
{ or: number },
{ xor: number },
{ and: number }
>;
const query1: BitwiseCondition = {
and: 5
};
const query: BitwiseCondition = {
and: 5,
or: 6 // raise a ts error
};
如果有人可以做得更好或更漂亮,请这样做
@mvasin FWIW,这个_appears_可以达到相同的结果,但是我完全同意它应该是接口的功能,就像在类型上一样。
type Foo = 'a' | 'b';
type Bar = {
[key in Foo]: any
}
interface A extends Bar { }
class Wol implements A{
a: any;
b: any;
}
对于打字稿3.5,看来我必须这样做:
export interface DataTableState {
columnStats: {[key in keyof DataTable]?:{}}
}
这是最好的方法吗?
为什么索引签名不能完全使用枚举类型? 映射的类型几乎可以满足我的要求,但是TypeScript希望枚举中的每个字符串都作为已定义的键存在。 我实际上并不想断言每个键都存在,更多的是,如果确实存在任何键,则它们必须存在于枚举中。
例如类型:
type MyType = {
[Key: 'foo' | 'bar' | 'zip']: number;
};
这应该满足:
const x: MyType = {
foo: 1,
zip: 2
};
虽然我可以为映射类型设置其他未定义的键,但是我更喜欢将这些键设置为可选键,但是如果它们存在,则值不能不确定。 如果我将映射的类型值设为可选,则代码可以工作,但类型不那么强。
使用Partial更好
type A = 'x' | 'y' | 'z'; type M = Partial<{ [key in A]: boolean }>;
谢谢!
当您需要定义部分与字典匹配的类型时很有用
“部分”也可以在记录中使用:
type Foo = 'a' | 'b';
let foo1: Record<Foo, number> = { a: 1, b: 2 };
let foo2: Partial<Record<Foo, number>> = { a: 1 };
我发现自己每个月左右都会不知不觉地访问此GitHub页面。
我的最新文章是一个真正简单的文章:
interface ObjectLiteral {
[key: string | number]: any
}
export const mapToObjectLiteral = (map: Map<string|number, any>) =>
Array.from(map).reduce((objLit, [key, value]) => {
objLit[key] = value
return objLit
}, {} as ObjectLiteral)
我可以向上滚动并找出一种解决方法,但只是想提供反馈,指出此问题在稍有不同的情况下的日常工作中经常发生。
这是一个例子:
type MapKey = string | number;
type ObjectLiteral<T extends MapKey, V = any> = {
[P in T extends number ? string : T]: V;
};
export const mapToObjectLiteral = <T extends MapKey, V>(map: Map<T, V>) =>
Array.from(map).reduce((objLit, [key, value]) => {
objLit[key as keyof ObjectLiteral<T>] = value;
return objLit;
}, {} as ObjectLiteral<T, V>);
// how to make a better type of map ?
const m = new Map<1 | "foo", "a" | "b">();
m.set(1, "a");
m.set("foo", "b");
const o = mapToObjectLiteral(new Map(m));
console.log(o[1], o.foo); // just got an union type of every member of 'o'
https://github.com/microsoft/TypeScript/issues/24220#issuecomment -504285702
要使用类再添加一个示例...
class Foo { a: string; b: string; } type Bar = {[key in keyof Foo]: any};
很有用。 谢谢! 🚀
最有用的评论
你可以这样做:
尽管
Bar
没有索引签名(即您不能再执行(obj as Bar)[value as Foo]
)。编辑:虽然如果您可以使警告无效,我将永远感激不已!