在打字稿中构建具有属性的功能对象
我想创建一个函数对象,该对象还具有一些属性。例如,在JavaScript中,我会做:
var f = function() { }
f.someValue = 3;
现在,在打字稿中,我可以将其描述为:
var f: { (): any; someValue: number; };
但是我实际上不能构建它,而不需要铸造。诸如:
var f: { (): any; someValue: number; } =
<{ (): any; someValue: number; }>(
function() { }
);
f.someValue = 3;
您如何在没有演员的情况下构建它?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
使用
object.assign(target,source)
示例:
魔术是
object.assign&lt; t, u&gt;(t:t,u:u)
键入以返回 Intersectiont&amp; u
。强制将其解决到已知接口也是直接的。例如:
由于不兼容的打字而引起的哪些错误:
caveat:您可能需要 polyfill object.sign如果针对较旧的浏览器。
This is easily achievable now (typescript 2.x) with
Object.assign(target, source)
example:
The magic here is that
Object.assign<T, U>(t: T, u: U)
is typed to return the intersectionT & U
.Enforcing that this resolves to a known interface is also straight-forward. For example:
which errors due to incompatible typing:
caveat: you may need to polyfill Object.assign if targeting older browsers.
更新:此答案是较早版本的打字稿中的最佳解决方案,但是较新版本中有更好的选项(请参阅其他答案)。
公认的答案有效,在某些情况下可能需要,但没有提供任何类型的安全性来构建对象的缺点。如果您尝试添加未定义的属性,此技术至少会丢弃类型错误。
Update: This answer was the best solution in earlier versions of TypeScript, but there are better options available in newer versions (see other answers).
The accepted answer works and might be required in some situations, but have the downside of providing no type safety for building up the object. This technique will at least throw a type error if you attempt to add an undefined property.
Typescript旨在通过 声明合并 a>:
声明合并的声明让我们说某物既是功能又是一个名称空间(内部模块):
这可以保留键入,并让我们同时编写
f()
和f.somevalue
。在编写.d.t.ts
为现有JavaScript代码的文件时,请使用neclare
:将属性添加到功能中通常是一个令人困惑或意外的模式,因此请避免它,但是,使用或转换较旧的JS代码时可能有必要。这是将内部模块(名称空间)与外部混合的唯一时间之一。
TypeScript is designed to handle this case through declaration merging:
Declaration merging lets us say that something is both a function and a namespace (internal module):
This preserves typing and lets us write both
f()
andf.someValue
. When writing a.d.ts
file for existing JavaScript code, usedeclare
:Adding properties to functions is often a confusing or unexpected pattern in TypeScript, so try to avoid it, but it can be necessary when using or converting older JS code. This is one of the only times it would be appropriate to mix internal modules (namespaces) with external.
因此,如果要求只需简单地将该函数构建并分配给“ f”,而无需演员,则可能是一个可能的解决方案:
本质上,它使用自我执行函数字面来“构造”一个对象,该对象将在分配为之前匹配该签名完毕。唯一的怪异是,该函数的内部声明必须为“任何”类型,否则编译器您要分配给对象上不存在的属性。
编辑:稍微简化了代码。
So if the requirement is to simply build and assign that function to "f" without a cast, here is a possible solution:
Essentially, it uses a self executing function literal to "construct" an object that will match that signature before the assignment is done. The only weirdness is that the inner declaration of the function needs to be of type 'any', otherwise the compiler cries that you're assigning to a property which does not exist on the object yet.
EDIT: Simplified the code a bit.
旧问题,但是对于以3.1开头的打字稿版本,只要您使用函数声明或
const
关键字,您就可以像在普通js中一样进行属性分配:< a href =“ https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-1.html#properties-declaraties-on-functions” rel =“ noreferrer”> 在线示例。
Old question, but for versions of TypeScript starting with 3.1, you can simply do the property assignment as you would in plain JS, as long as you use a function declaration or the
const
keyword for your variable:Reference and online example.
作为快捷方式,您可以使用['属性']访问者动态分配对象值:
这绕过类型检查。但是,这是非常安全的,因为您必须以相同的方式故意访问该属性:
但是,如果您真的希望使用该类型检查属性值,则这将无法使用。
As a shortcut, you can dynamically assign the object value using the ['property'] accessor:
This bypasses the type checking. However, it is pretty safe because you have to intentionally access the property the same way:
However, if you really want the type checking for the property value, this won't work.
我不能说这很简单,但绝对有可能:
如果您感到好奇可选
I can't say that it's very straightforward but it's definitely possible:
if you got curious this is from a gist of mine with the TypeScript/JavaScript version of
Optional
一个更新的答案:由于通过
&amp;
添加了相交类型,因此可以随时“合并”两种推断类型。这是一个通用的助手,它从中读取某些对象
的属性,然后将它们通过对象
将其复制到
上。它将同一对象返回到
上设计安全。使用该辅助器,我们有一个操作员,可以使用该操作员使用全类型安全来解决OP的问题:
单击此处在打字稿游乐场中尝试一下。请注意,我们已将
foo
限制为类型foo
,因此Merge
的结果必须是完整的foo
。因此,如果您将bar
重命名为bad
,则会获得类型错误。nb 但是,这里仍然有一个类型的孔。 Typescript不能提供将类型参数限制为“不是函数”的方法。因此,您可能会感到困惑,并将您的函数作为第二个参数将其传递给
Merge
,这是行不通的。因此,直到可以宣布这一点,我们必须在运行时抓住它:An updated answer: since the addition of intersection types via
&
, it is possible to "merge" two inferred types on the fly.Here's a general helper that reads the properties of some object
from
and copies them over an objectonto
. It returns the same objectonto
but with a new type that includes both sets of properties, so correctly describing the runtime behaviour:This low-level helper does still perform a type-assertion, but it is type-safe by design. With this helper in place, we have an operator that we can use to solve the OP's problem with full type safety:
Click here to try it out in the TypeScript Playground. Note that we have constrained
foo
to be of typeFoo
, so the result ofmerge
has to be a completeFoo
. So if you renamebar
tobad
then you get a type error.NB There is still one type hole here, however. TypeScript doesn't provide a way to constrain a type parameter to be "not a function". So you could get confused and pass your function as the second argument to
merge
, and that wouldn't work. So until this can be declared, we have to catch it at runtime:这与强大的打字相反,但是如果您想像我发现这个问题时那样,您可以
像我那样绕过压迫性强的打字。可悲的是,这是一个案例打字稿在完全有效的JavaScript上失败,因此您必须告诉Typescript退缩。
“您的javaScript是完全有效的打字稿”评估为false。 (注意:使用0.95)
This departs from strong typing, but you can do
if you are trying to get around oppressive strong typing like I was when I found this question. Sadly this is a case TypeScript fails on perfectly valid JavaScript so you have to you tell TypeScript to back off.
"You JavaScript is perfectly valid TypeScript" evaluates to false. (Note: using 0.95)