采用没有特定键的对象的 TypeScript 函数

标签 typescript

试着创建一个函数,该函数接受一个参数对象,该对象不能有一些键集,而不是让人们手动指定类型。我试图以某种方式利用 never,但我陷入了试图理解推理如何适用于接受具有泛型参数的类型的函数参数的过程。

interface ReservedAttributes {
    someKey: string
}

// evaluates to never if the type has a key that intersects 
// with the keys in ReservedAttributes
type ValidAttributes<T> = keyof T extends Exclude<keyof T, keyof ReservedAttributes> ? T : never

// This is correctly a never, but it doesn't address this problem
type Test = ValidAttributes<{someKey : string}>


// This doesn't work because the function argument ends 
// up being inferred as { [name: string] : string}
function foo1<K extends { [name: string] : string}>(attributes: ValidAttributes<K>)  {
    // ...
}
foo1({a: 'hi', someKey: ''})

// Roughly equivalent to the above
function foo2< K extends { [name: string] : string}, V extends ValidAttributes<K> >(attributes: V)  {
    // ...
}

// This one allows V to correctly evaluate to never, 
// but I'm not sure how to leverage that
function foo3< K extends { [name: string] : string}, V extends ValidAttributes<K> >(attributes: K)  {
    // ...
}
foo3({a: 'hi', someKey: ''})

你会如何解决这个问题?

最佳答案

我想我会先尝试远离泛型和条件类型,然后做这样的事情:

type ValidAttributes = Record<string, string> &
  Partial<Record<keyof ReservedAttributes, never>>;
declare function foo(attributes: ValidAttributes): void;

foo({ a: 'hi' }); // okay
foo({ a: 'hi', someKey: '' }); // error, someKey

在这种情况下,ValidAttributes 是一个通用的字符串值字典,但是 ReservedAttributes 中的键被列为 never 类型的可选属性(允许缺少可选属性,并且类型 never 的属性实际上不允许存在,因此 never 类型的可选属性或多或少是必须的缺少。)这对你有用吗?

如果您需要在泛型约束中使用条件类型,可以这样做:

type Attributes<K extends keyof any> = {
  [P in K]: P extends keyof ReservedAttributes ? never: string
};
declare function foo<T>(attributes: T & Attributes<keyof T>): void;
foo({ a: 'hi' }); // okay
foo({ a: 'hi', someKey: '' }) // error

但它更复杂并且达到类似的结果。希望有所帮助;祝你好运!

关于采用没有特定键的对象的 TypeScript 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52618362/

相关文章:

javascript - 你如何防止 sequelize 中的嵌套查询/捕获?

typescript - Angular2 和 TypeScript : error TS2322: Type 'Response' is not assignable to type 'UserStatus'

TypeScript:使用 Map 中的键作为类型

javascript - 按文件扩展 Monaco Editor 提示

Angular + amazon-cognito-identity-js,为什么我收到错误 : global is not defined

Angular 4 找不到名称(泛型)

typescript - 为什么交集类型可以包含冲突类型?

typescript 只采用接口(interface)中定义的属性

类型的 typescript 传播运算符

javascript - 在 Typescript/Javascript ES6 中以编程方式获取同一文件中模块的所有导出