Typescript中使用Object.assign报错 : Property ‘assign’ does not exist on type ‘ObjectConstructor’

本文介绍在Typescript中使用Object.assign方法时遇到的编译错误,并提供解决方案,通过类型断言让代码顺利编译。同时,分享了Object.assign的浅拷贝特性及其实现原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在Typescript中使用Object.assign报错:Property ‘assign’ does not exist on type ‘ObjectConstructor’


使用引擎编译后的ts会转为js,方法是可以用的,主要是为了解决在ts中使用该方法编译器报错导致无法运行

解决方法:

使用类型断言(Type Assertion),对Object进行具体类型的指定(指定不是转换),使用<>as 关键字都可以,指定为any

(<any>Object).assign(obj1, obj2);

另外,深克隆请查看:关于数据的深克隆方法


拓展

Object.assign是浅拷贝,知道原理就可以重写一个新的方法

下面这段代码来自:Object.assign 原理及其实现——@木易杨

if (typeof Object.assign2 != 'function') {
  // Attention 1
  Object.defineProperty(Object, "assign2", {
    value: function (target) {
      'use strict';
      if (target == null) { // Attention 2
        throw new TypeError('Cannot convert undefined or null to object');
      }

      // Attention 3
      var to = Object(target);
        
      for (var index = 1; index < arguments.length; index++) {
        var nextSource = arguments[index];

        if (nextSource != null) {  // Attention 2
          // Attention 4
          for (var nextKey in nextSource) {
            if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
              to[nextKey] = nextSource[nextKey];
            }
          }
        }
      }
      return to;
    },
    writable: true,
    configurable: true
  });
}
//使用方法
Object.assign2(obj1, obj2);

维尼聚合工具


<think>我们正在解决CocosCreator中的错误:Property'director'doesnotexistontype'never'这个错误通常发生在TypeScript的类型推断失败,将变量推断为`never`类型,然后你试图访问这个变量上的`director`属性(例如:`this.node.parent.director`)。`never`类型表示一个永远不会存在的值的类型,因此它没有任何属性。常见场景:1.在访问一个可能为空的节点属性(如`parent`)时,TypeScript推断该属性可能为`null`,并且在某个分支中变成了`never`。2.在条件判断中,如果已经排除了所有可能,那么剩下的类型就是`never`。例如:```typescriptletparent=this.node.parent;//如果parent可能为null,那么下面条件判断后,else分支中parent就是never类型if(parent){//在这里parent是非空的}else{//在这里parent是null,所以访问parent.director就会出错console.log(parent.director);//错误:Property'director'doesnotexistontype'never'}```但是,通常我们遇到这个错误是在非条件分支中,比如直接访问`this.node.parent.director`。这是因为`this.node.parent`的类型可能是`null|cc.Node`,而`null`上没有`director`属性。然而,注意:`cc.Node`本身也没有`director`属性。实际上,`director`是`cc.director`,它是CocosCreator引擎的全局对象,通常通过`cc.director`访问。所以,这个错误可能有两个原因:原因1:你错误地认为某个节点(如父节点)有`director`属性,实际上并没有。原因2:你在一个可能为`null`或`undefined`的值上访问属性,而TypeScript的类型推断认为这个值在当前位置是`never`类型(通常是因为前面的条件已经排除了其他类型,只剩下不可能的类型)。解决方案:1.确认你是否需要访问`cc.director`而不是某个节点的`director`属性。如果是,那么直接使用`cc.director`。例如,将`this.node.parent.director`改为`cc.director`。2.如果你确实需要访问一个可能为空的节点上的属性,那么你需要先检查该节点是否存在(非空)。例如:```typescriptletparent=this.node.parent;if(parent){//现在TypeScript知道parent是cc.Node类型(非空)//但是注意:cc.Node并没有director属性,所以下面这行仍然会报错,除非你确定parent上有这个属性(通常没有)//所以,你可能还是需要cc.directorletdirector=parent.director;//如果parent是cc.Node,这里仍然会报错,因为cc.Node没有director}```3.如果你确定某个节点上有一个自定义的`director`属性(比如你自己挂的脚本),那么你需要确保TypeScript知道这一点。你可以通过类型断言或者声明合并来实现。例如,使用类型断言:```typescriptletparent=this.node.parentascc.Node&{director:any};//或者更具体的类型if(parent){letdirector=parent.director;//现在可以了}```4.如果你遇到的是在条件分支中TypeScript推断为`never`,那么你需要检查你的条件逻辑。确保在访问属性之前,变量是存在的。5.另一种可能是你在使用`getComponent`时没有指定正确的类型,导致返回`null`,然后你尝试访问这个组件上的属性。例如:```typescriptletcomp=this.getComponent(MyComponent);//如果当前节点没有这个组件,comp为nullcomp.doSomething();//如果comp为null,这里会报错```解决方案:检查组件是否存在。```typescriptletcomp=this.getComponent(MyComponent);if(comp){comp.doSomething();}```6.如果你在使用`getComponent`时遇到类型为`never`,可能是因为你使用了错误的类型。确保你传入的类型是正确的。7.使用非空断言操作符(`!`)来告诉TypeScript这个值一定存在(但请谨慎使用,因为如果确实为空,运行时将会报错)。```typescriptletparent=this.node.parent!;//断言parent非空//然后访问parent.director,但同样,parent是cc.Node,通常没有director属性```总结:大多数情况下,你不需要访问节点上的`director`,而是直接使用`cc.director`。所以请先检查你的代码是否误写了。如果问题仍然存在,请提供具体的代码片段,以便更准确地定位问题。下面是一个示例,展示如何正确使用`cc.director`:```typescriptconst{ccclass}=cc._decorator;@ccclassexportdefaultclassGameControllerextendscc.Component{onLoad(){//暂停游戏cc.director.pause();}}```如果你在代码中写的是`this.director`,那么请注意,只有从`cc.Component`继承的类中,`this`指向组件实例,而组件实例并没有`director`属性。同样,如果你写的是`this.node.director`,节点也没有这个属性。因此,请将代码中的`xxx.director`改为`cc.director`。如果这样做之后,错误消失,那么问题就解决了。如果错误出现在其他情况下,请根据上述方案进行排查。§§相关问题§§1.CocosCreator中如何正确使用cc.director?2.如何解决TypeScript中类型推断为never的问题?3.CocosCreator中节点和组件的关系是什么?4.如何在CocosCreator中安全地访问可能为空的节点或组件?</think>### Cocos Creator 报错 "Property 'director' does not exist on type 'never'" 解决方案 这个错误通常发生在 TypeScript 类型系统推断出某个对象的类型为 `never` 时(表示该值理论上不可能存在),而你却尝试访问它的 `director` 属性。以下是常见原因和解决方案: --- #### 常见原因与解决方案 1. **组件获取失败时的类型推断** ```typescript // 错误示例 let comp = this.getComponent(MyComponent); // comp 可能为 null comp.doSomething(); // 报错: Property 'doSomething' does not exist on type 'never' ``` ✅ **解决方案:添加空值检查** ```typescript let comp = this.getComponent(MyComponent); if (comp) { // 显式检查 null/undefined comp.doSomething(); // ✅ 安全访问 } ``` 2. **未初始化的类成员** ```typescript class GameManager { private director: cc.Director; // 未初始化 start() { this.director.pause(); // 报错: Property 'director' does not exist on type 'never' } } ``` ✅ **解决方案:明确初始化** ```typescript class GameManager { private director: cc.Director = cc.director; // ✅ 直接初始化 start() { this.director.pause(); } } ``` 3. **类型守卫失效** ```typescript function handleNode(node: cc.Node | null) { if (!node) return; // 此处 TypeScript 仍可能推断为 never node.getComponent(cc.Label).string = "Text"; // 可能报错 } ``` ✅ **解决方案:使用类型断言** ```typescript function handleNode(node: cc.Node | null) { if (!node) return; const label = node.getComponent(cc.Label) as cc.Label; // ✅ 类型断言 label.string = "Text"; } ``` 4. **访问不存在的节点路径** ```typescript // 错误示例 let childNode = this.node.getChildByName("NonExistent"); childNode.active = false; // 报错 ``` ✅ **解决方案:验证节点存在性** ```typescript let childNode = this.node.getChildByName("NonExistent"); if (childNode) { // ✅ 验证存在性 childNode.active = false; } ``` --- #### 高级调试技巧 1. **严格模式检查**(在 `tsconfig.json` 中): ```json { "compilerOptions": { "strict": true, // 启用所有严格检查 "strictNullChecks": true // 重点关注此项 } } ``` 2. **运行时类型保护**: ```typescript function isDirector(obj: any): obj is cc.Director { return obj && typeof obj.pause === "function"; } if (isDirector(someObj)) { someObj.pause(); // ✅ 安全调用 } ``` 3. **使用可选链操作符**(TypeScript 3.7+): ```typescript // 安全访问深层属性 this.node.parent?.getComponent(Player)?.health; ``` --- #### 实际应用示例 ```typescript const { ccclass, property } = cc._decorator; @ccclass export default class GameCtrl extends cc.Component { private mainDirector: cc.Director = null; onLoad() { // ✅ 正确初始化 this.mainDirector = cc.director; // ✅ 安全访问组件 const player = this.node.getComponent("Player") as Player; if (player) { player.initialize(); } } pauseGame() { // ✅ 直接使用全局 director cc.director.pause(); // ✅ 或使用已初始化的成员 this.mainDirector.pause(); } } ``` > **关键点**:`cc.director` 是 Cocos Creator 的全局单例对象[^1],应直接通过 `cc.director` 访问,而非从节点获取。 --- #### 类型系统最佳实践 1. 避免使用 `any`,优先使用具体类型或接口 2. 初始化类成员时直接赋值 `= cc.director` 3. 使用非空断言 `!` **仅当 100% 确定非空时** ```typescript // 谨慎使用 this.node.getChildByName("UI")!.active = true; ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值