TypeScript:告诉对象它可以拥有哪些键和值
TypeScript: Tell object which keys and values it can have
我有一个代表某些常量之一的类型。每种类型也有特定的回调函数。
type MyType = 'A' | 'B' | 'C';
// Same for 'B', 'C' etc.
type callbackForA = (result: ResultForA) => void;
ResultForA
是属于 A
.
的特定对象
我想为 可能有 键的对象创建一个 TypeScript type
或 interface
(我们称之为 MagicType
)对于这些 MyType
个常量中的每一个。这些键中的每一个的值可以是 true
(或隐式 undefined
因此 "可能有")或可能是具有特定调用签名的回调函数基于类型。
以下应该是有效的 MagicType
对象:
const myObject: MagicType = {
'A': true | (result: ResultForA) => void,
'C': true;
}
其中 B
未配置,并且 C
不接受回调。
以下应该是 MagicType
的无效对象。
const myObject: MagicType = {
'A': true | (result: ResultForB) => void;
'FOO': true
}
因为 A
有错误的回调函数 (result: ResultForB) => void
并且 FOO
不是 MyType
的有效选项。
如何实现这样的类型?
我尝试的是像这样扩展 Result
类型:
type CallbackFunctionVariadicAnyReturn = (...args: any[]) => any
interface MagicType extends Record<MyType, true | CallbackFunctionVariadicAnyReturn>;
不幸的是,它既没有检测到多余的键,例如 FOO
,也没有检测到错误的回调函数。
额外的想法/问题:
是否还有一种方法可以将回调与每个 MyType
值紧密耦合?也许是这样的元组?
type MyTypePairs = ['A', (result: ResultForA) => void] | ['B', // ...
type MagicType = {
'A': boolean | (result: ResultForA) => void,
'B': undefined,
'C': boolean,
}
所做的是为三个键中的每一个添加类型注释,并且由于 TS 不允许使用列出的键以外的任何键,因此您不能使用 'FOO'
键,并且回调上的注释意味着您不能在 a.
上执行 (result: ResultForB) => void
回调
// define your types
type ResultForA = { a: string };
interface ResultCollection {
A: ResultForA; // can use named type alias
B: { b: boolean }; // or simply inline your result types
C: { c: number };
}
// Bonus thought / question:
type ResultFunc<K extends keyof ResultCollection> = (result: ResultCollection[K]) => void;
// Tell object which keys and values it can have
type MagicType = Partial<{[K in keyof ResultCollection]: ResultFunc<K> | boolean}>;
// examples
const good1: MagicType = { // ok
A: true,
B: (r: { b: boolean }) => {
console.log(r);
},
};
const good2: MagicType = { // ok
A: (r: { a: string }) => {},
B: (r: { b: boolean }) => {
console.log(r);
},
C: false
};
const bad1: MagicType = {
Foo: true, // error
}
const bad2: MagicType = {
B: (r: { c: number }) => { // error
console.log('not a good b');
},
};
为此,您需要创建映射数据结构,它将每个允许的键映射到某个 type/value。
考虑这个例子:
type MyMap = {
A: "#A",
B: '#B',
C: '#C'
}
type MyType = keyof MyMap
type ResultForA = '#A'
type ResultForB = '#B'
type ResultForC = '#C'
type MagicType<Dict> = {
[Prop in keyof Dict]?: true | ((value: Dict[Prop]) => void)
}
type Result = MagicType<MyMap>
类型 MyMap
是地图数据结构,您可能已经猜到了。
MagicType
是在 mapped types
的帮助下构建的
我有一个代表某些常量之一的类型。每种类型也有特定的回调函数。
type MyType = 'A' | 'B' | 'C';
// Same for 'B', 'C' etc.
type callbackForA = (result: ResultForA) => void;
ResultForA
是属于 A
.
我想为 可能有 键的对象创建一个 TypeScript type
或 interface
(我们称之为 MagicType
)对于这些 MyType
个常量中的每一个。这些键中的每一个的值可以是 true
(或隐式 undefined
因此 "可能有")或可能是具有特定调用签名的回调函数基于类型。
以下应该是有效的 MagicType
对象:
const myObject: MagicType = {
'A': true | (result: ResultForA) => void,
'C': true;
}
其中 B
未配置,并且 C
不接受回调。
以下应该是 MagicType
的无效对象。
const myObject: MagicType = {
'A': true | (result: ResultForB) => void;
'FOO': true
}
因为 A
有错误的回调函数 (result: ResultForB) => void
并且 FOO
不是 MyType
的有效选项。
如何实现这样的类型?
我尝试的是像这样扩展 Result
类型:
type CallbackFunctionVariadicAnyReturn = (...args: any[]) => any
interface MagicType extends Record<MyType, true | CallbackFunctionVariadicAnyReturn>;
不幸的是,它既没有检测到多余的键,例如 FOO
,也没有检测到错误的回调函数。
额外的想法/问题:
是否还有一种方法可以将回调与每个 MyType
值紧密耦合?也许是这样的元组?
type MyTypePairs = ['A', (result: ResultForA) => void] | ['B', // ...
type MagicType = {
'A': boolean | (result: ResultForA) => void,
'B': undefined,
'C': boolean,
}
所做的是为三个键中的每一个添加类型注释,并且由于 TS 不允许使用列出的键以外的任何键,因此您不能使用 'FOO'
键,并且回调上的注释意味着您不能在 a.
(result: ResultForB) => void
回调
// define your types
type ResultForA = { a: string };
interface ResultCollection {
A: ResultForA; // can use named type alias
B: { b: boolean }; // or simply inline your result types
C: { c: number };
}
// Bonus thought / question:
type ResultFunc<K extends keyof ResultCollection> = (result: ResultCollection[K]) => void;
// Tell object which keys and values it can have
type MagicType = Partial<{[K in keyof ResultCollection]: ResultFunc<K> | boolean}>;
// examples
const good1: MagicType = { // ok
A: true,
B: (r: { b: boolean }) => {
console.log(r);
},
};
const good2: MagicType = { // ok
A: (r: { a: string }) => {},
B: (r: { b: boolean }) => {
console.log(r);
},
C: false
};
const bad1: MagicType = {
Foo: true, // error
}
const bad2: MagicType = {
B: (r: { c: number }) => { // error
console.log('not a good b');
},
};
为此,您需要创建映射数据结构,它将每个允许的键映射到某个 type/value。 考虑这个例子:
type MyMap = {
A: "#A",
B: '#B',
C: '#C'
}
type MyType = keyof MyMap
type ResultForA = '#A'
type ResultForB = '#B'
type ResultForC = '#C'
type MagicType<Dict> = {
[Prop in keyof Dict]?: true | ((value: Dict[Prop]) => void)
}
type Result = MagicType<MyMap>
类型 MyMap
是地图数据结构,您可能已经猜到了。
MagicType
是在 mapped types