首页 > 解决方案 > 为什么在将 TypeScript 属性设置为未定义之前设置它们如此困难?TypeError:无法设置未定义的属性“x”

问题描述

每次我必须处理它时,这都会让我发疯。我无法告诉你我遇到的额外编码时间,我觉得这是 TypeScript 的一个缺陷。

undefined我必须设置一个属性才能用实际值设置它对我来说没有任何意义。

这是示例:

// why do i have to do this?
this.aClass.aInterface: ClassAndInterface = {
    aProperty: undefined
}
this.aClass.aInterface.aProperty: ClassAndInterface = {
    name: 'The Name',
    description: 'A description'
};

我觉得这个错误应该有一些东西来设置一个可以用来减轻这个错误的属性。如果我试图设置属性,那么它未定义的事实对我来说不是一个问题,尤其是当值是可选的时。

标签: javascripttypescript

解决方案


我认为这是一个很好的答案,为什么会发生这种情况,以及为什么TypeScript与自己编写相比更容易遇到这个问题js

问题源于在 Typescript 中更容易使用类和对象,而不是你显然不能用 js 做同样的事情。但是,当您开始对接口和类使用接口和类型时,这可能是更需要理解的地方。

问题真正来自于将财产带到远处。人们实际上发布了很多关于这个确切问题的帖子,据我所知,这是真正意义上的误解。

究竟是什么误解?正如@jcalz 在上述消息中发布的那样

let x; 
x.a = 123 // NO <<< you can't do that

真的就是这么简单。但是,当您编写漂亮且格式良好的对象时,您可以快速执行此类操作。

x = {
   a: 3
}
x.a = 3; <<< this is OK

这一切都很好并且可以理解,所以为什么Typescript总是让我犯这个错误。答案实际上是当您尝试负责并编写类型为属性的类和接口时,您走得太远了一级。

当我说一级过分时,我是什么意思?当您尝试获取基类和/或接口并从该基类设置接口属性的属性时。它可能是一个相同的分类类型属性。

此时,您正在处理技术上尚未定义的属性。

您应该怎么做才能缓解问题并且不会在您的编码中导致错误或错误?

您应该做的是直接使用设置为该接口的新属性对该接口进行操作。如果它是一堂课,你也可以这样做。之后,您应该将基本属性直接设置为接口和/或类的新属性。(这显示在下面的代码示例中)

另外,正如我发现的那样,您可能需要这样做,您可以将属性设置为未定义。这种方法伴随着警钟、代码气味和警告。

  1. 您必须将该接口或类中的每个属性设置为未定义或某个值(启动)
  2. 您已经处理了将上游的每个属性都设置为未定义的事实,这意味着您可能不想在对象中携带一堆未定义的值。
  3. 下游需要大量的保护(if 语句)和保护,这样您就不会遇到运行时错误
  4. 感觉像代码气味,可能是
  5. 什么是代码异味?我不确切知道,但你应该这样做 我知道而且它实际上并没有气味

那么,你为什么要这样做而不是以正确的方式去做呢?好吧,就我而言,我正在将一个对象从一个类传递到另一个类,并且我试图使用那个会再次完整返回的确切对象。

相反,我应该做的是传递一个带有基础对象和新对象 {base: baseObj, new: newObj} 的新对象,然后返回这两个对象。

无论如何,我已经包含了一些代码,你可以去操场玩Typescript Editor,看看我在说什么,以及使用一种方法与另一种方法有什么区别。

interface SomeInterface {
    interFaceProp1: string|undefined;
    interFaceProp2?: string;
}

class SomeClass {
    public prop1: SomeInterface|undefined;
    prop2: string|undefined;
    prop3!: string;
}
let localProp = new SomeClass();
// this is to mitigate an issue
// localProp.prop1 = {
//     interFaceProp1: undefined
// }
/** or instead do this so that it makes more sense and is accurate to the capability of the object
* and to what is the expected output of the object 
*/
let otherLocalProp: SomeInterface;
otherLocalProp = {
    interFaceProp1: 'Tristan'
}
console.log(otherLocalProp.interFaceProp1);
localProp.prop1 = otherLocalProp;
localProp.prop1.interFaceProp1 = 'Carlos';
console.log(localProp.prop1.interFaceProp1);
console.log(otherLocalProp.interFaceProp1);
otherLocalProp.interFaceProp1 = 'Christian'
console.log(localProp.prop1);

推荐阅读