typescript 筛选名称为联合类型的对象数组

pbossiut  于 2023-01-21  发布在  TypeScript
关注(0)|答案(2)|浏览(119)

我有一个数组,我想用typescript过滤,但是我不能让typescript验证端工作,我有一个操作数组,我想过滤掉内部操作(见下文)-但是我不能告诉typescript filteredActions数组不再包含internalAction!
我是这么试的

type ActionName = 'replaceText' | 'replaceImage' | 'internalAction';

interface Action {
  name: ActionName
}
const INTERNAL_ACTIONS = ['internalAction'] as const;
type InternalActions = typeof INTERNAL_ACTIONS[number];

const actions: Action[] = [{
   name: 'replaceText'
}, {
   name: 'replaceImage'
}, {
   name: 'internalAction'
}];
const isInternalAction = (name: ActionName): name is Exclude<ActionName, InternalActions> => name in INTERNAL_SLIDE_ACTIONS;
const filteredActions = actions.filter((action) => !isInternalAction(action.name));
for (const action of filteredActions) {
  if (action.name === 'internalAction') {
    // i'd expect TS to throw an error here as internalAction should never appear
  }
  if (action.name === 'replaceImage') {
    // i'd expect TS to NOT throw an error here
  }
}
xfb7svmp

xfb7svmp1#

isInternalAction箭头功能存在问题。
要检查typescript中数组的元素是否不能使用in operator,但可以用途:includessomefindindexOf(也许还有其他选项,但这些都在我的头顶上)
因此我将代码更改为例如:

type ActionName = 'replaceText' | 'replaceImage' | 'internalAction';

interface Action {
  name: ActionName
}
const INTERNAL_ACTIONS: readonly ActionName[] = ['internalAction'] as const;
type InternalActions = typeof INTERNAL_ACTIONS[number];

const actions: Action[] = [{
  name: 'replaceText'
}, {
  name: 'replaceImage'
}, {
  name: 'internalAction'
}];

// use includes to check if element exists in an array
const isInternalAction = (name: ActionName): boolean => INTERNAL_ACTIONS.includes(name);
const filteredActions = actions.filter((action) => !isInternalAction(action.name));

console.log(filteredActions)

在这里,您可以在ts-playground中找到并运行上面的代码段

lymnna71

lymnna712#

关键在于过滤器,我必须重新绑定动作,并排除名称:

const filteredActions = slide.actions.filter((action): action is Omit<Action, 'name'> & {
    name: Exclude<ActionName, InternalActions>
} => typeof INTERNAL_ACTIONS.find(i => i === action.name) === 'undefined');

这样,过滤后的每个操作都具有正确的类型

相关问题