[英]How to check the type of a type union in a function in typescript
Say I have this code:说我有这段代码:
interface A {
type: 'a',
value : number
}
interface B {
type: 'b',
value: string
}
type AB = A | B;
const db: Record<string, AB> = {
param1: { type: 'a', value: 1234 }
};
I have code like this (over-simplified) that works well我有这样的代码(过度简化)效果很好
function processParameter(parameter: string, expectedType: 'a' | 'b') {
if (expectedType === 'a') {
const result = db[parameter];
if(!result) { throw new Error('Not found'); }
if(result.type !== 'a') { throw new Error('Unexpected type'); }
processA(result);
}
if (expectedType === 'b') {
const result = db[parameter];
if(!result) { throw new Error('Not found'); }
if(result.type !== 'b') { throw new Error('Unexpected type'); }
processB(result);
}
}
function processA(value: A) {
// ...
}
function processB(value: B) {
// ...
}
I would like to refactor the code like this:我想像这样重构代码:
function processParameter(parameter: string, expectedType: 'a' | 'b') {
if (expectedType === 'a') {
const result = getAndCheck(parameter, expectedType);
processA(result);
}
if (expectedType === 'b') {
const result = getAndCheck(parameter, expectedType);
processB(result);
}
}
// I don't want to write all those lines here, is there a way ?
function getAndCheck(parameter: string, expectedType: 'a'): A;
function getAndCheck(parameter: string, expectedType: 'b'): B;
function getAndCheck(parameter: string, expectedType: 'a' | 'b'): AB {
const result = db[parameter];
if(!result) { throw new Error('Not found'); }
if(result.type !== expectedType) { throw new Error('Unexpected type'); }
return result;
}
Is there a way to simplify that?有没有办法简化它? Using generic?
使用泛型? using inference?
使用推理? am I going the wrong way?
我走错路了吗?
You can use a generic function to establish a relation between the expectedType
parameter and the return type:您可以使用通用 function 在
expectedType
参数和返回类型之间建立关系:
function getAndCheck<K extends AB['type']>(parameter: string, expectedType: K): Extract<AB, { type: K }> {
const result = db[parameter] as AB;
if (!result) { throw new Error('Not found'); }
if (result.type !== expectedType) { throw new Error('Unexpected type'); }
return result as Extract<AB, { type: K }>;
}
Here we use a type parameter K
to capture the actual type that is passed in and we ensure that only a type in the union AB
can be passed in (we use an index access type to get the union of all possible types).这里我们使用类型参数
K
来捕获传入的实际类型,并确保只能传入联合AB
中的类型(我们使用索引访问类型来获取所有可能类型的联合)。 We then use Extract
to get the appropriate element from the union.然后我们使用
Extract
从联合中获取适当的元素。 (You can read a bit more abotut filtering unions here ) (你可以在这里阅读更多关于过滤联合的内容)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.