你能声明一个允许 typescript 中的未知属性的对象字面量类型吗?

Posted

技术标签:

【中文标题】你能声明一个允许 typescript 中的未知属性的对象字面量类型吗?【英文标题】:Can you declare a object literal type that allows unknown properties in typescript? 【发布时间】:2017-03-10 17:05:13 【问题描述】:

基本上我想确保一个对象参数包含所有必需的属性,但可以包含它想要的任何其他属性。例如:

function foo(bar:  baz: number ) : number 
    return bar.baz;


foo( baz: 1, other: 2 );

但这会导致:

Object literal may only specify known properties, and 'other' does not exist in type ' baz: number; '.

【问题讨论】:

【参考方案1】:

是的,你可以。试试这个:

interface IBaz 
    baz: number;
    [key: string]: any;


function foo(bar: IBaz) : number 
    return bar.baz;


foo( baz: 1, other: 2 );

【讨论】:

我最初是这么想的,但想要内联...(出于某种原因,我用括号而不是方括号搞砸了 [key: string] 部分)... 您不必使用any,只需确保包含| number(在此示例中),否则您将在baz: number; 上收到TS 错误。或者你可以使用unknown【参考方案2】:

好吧,我讨厌回答自己的问题,但其他答案激发了我的一些想法……这很有效:

function foo<T extends  baz: number >(bar: T): void 
    console.log(bar.baz);


foo(baz: 1, other: 2);

【讨论】:

这看起来你已经设置了它,所以函数接受一个类型参数,但你没有给它一个类型参数。你介意解释一下你在这里做什么吗?谢谢。 他让 TS 根据传递给 bar 参数的值自动推断类型参数。 额外属性应该影响返回类型或被跟踪的应用程序,这是最正确的解决方案。【参考方案3】:

如果已知字段来自泛型类型,则允许使用通配符的方法是使用T &amp; [key: string]: unknown,任何已知字段都必须符合类型的约束,并且允许其他字段(并视为类型unknown

这是一个示例:

type WithWildcards<T> = T &  [key: string]: unknown ;

function test(foo: WithWildcards<baz: number>) 

test( baz: 1 ); // works
test( baz: 1, other: 4 ); // works
test( baz: '', other: 4 ); // fails since baz isn't a number

如果你有一个泛型类型T,你可以允许带有WithWildCards&lt;T&gt;的通配符字段

请注意,如果对象来自对象文字以外的任何内容,则不会将额外的属性标记为错误,TS 只是告诉您,在文字中输入该属性是无关的。

Here are some other cases where extra properties are and aren't allowed

interface Foos
  a?: string
  b?: string

type WithWildcards<T> = T &  [key: string]: unknown ;

declare function acceptFoos(foo: Foos): void;
declare function acceptWild(foo: WithWildcards<Foos>):void

acceptFoos(  a:'', other: '') // ERROR since the property is extraneous
const data = a:'', other: ''
acceptFoos(  data) // allowed since it is compatible, typescript doesn't force you to remove the properties
const notCompat = other: ''
acceptFoos(notCompat) //ERROR: Type ' other: string; ' has no properties in common with type 'Foos'
acceptFoos(a:'', ...notCompat) // this is also allowed 
acceptWild(notCompat) // allowed

【讨论】:

【参考方案4】:

如果要允许整个对象的未知属性,可以使用Record

function doStuff(payload: Record<string|number, unknown>): Record<string|number, unknown> 
  return  anyProp: 'anyValue' 


【讨论】:

【参考方案5】:

这可以通过为函数参数定义类型定义来最容易地完成。下面是一个内联类型定义的例子:

function foo(bar:  baz: number ) : number 
    return bar.baz;


const obj =  baz: 1, other: 2 ;

foo(obj);

【讨论】:

这似乎会导致另一个类似这样的消息:Type ... has no properties in common with type '...'p using typescript 2.3.4 这是如何工作的?如果您将对象内联,则它不起作用。 这是一个内联类型定义,而不是一个内联对象。在TS Playground 中运行良好。【参考方案6】:

使用unknown 类型时,您可以使用narrowing 的概念来检查您希望从您正在经历的值中获得的类型,并根据您的需要操作这些值 例如

const messages: string []=Object.values(obj).map(val: unknown=>typeof obj==='object'?obj!['message']:obj)

【讨论】:

以上是关于你能声明一个允许 typescript 中的未知属性的对象字面量类型吗?的主要内容,如果未能解决你的问题,请参考以下文章

TypeScript 本地化问题

Typescript等效的包范围?

Java Spring:出现错误“未知属性子元素:<util:constant>”

为啥我的 Typescript 对象允许这个额外的属性?

Typescript 推断的泛型类型在条件类型中是未知的

C ++中的未知构造/变量声明[重复]