Mic*_*nko 45 javascript typescript angular
在我的Angular应用程序中,我有一个组件:
import { MakeService } from './../../services/make.service';
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-vehicle-form',
templateUrl: './vehicle-form.component.html',
styleUrls: ['./vehicle-form.component.css']
})
export class VehicleFormComponent implements OnInit {
makes: any[];
vehicle = {};
constructor(private makeService: MakeService) { }
ngOnInit() {
this.makeService.getMakes().subscribe(makes => { this.makes = makes
console.log("MAKES", this.makes);
});
}
onMakeChange(){
console.log("VEHICLE", this.vehicle);
}
}
Run Code Online (Sandbox Code Playgroud)
但在"制造"属性中我有一个错误.我不知道该怎么做...
Ste*_*ane 81
Property has no initializer and is not definitely assigned in the constructor
当我们在文件中添加一些配置tsconfig.json
以便以严格模式编译 Angular 项目时,我们可能会收到以下消息:
"compilerOptions": {
"strict": true,
"noImplicitAny": true,
"noImplicitThis": true,
"alwaysStrict": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"strictPropertyInitialization": true,
Run Code Online (Sandbox Code Playgroud)
事实上,编译器会抱怨成员变量在使用之前没有定义。
对于编译时未定义的成员变量的示例,具有@Input
指令的成员变量:
@Input() userId: string;
Run Code Online (Sandbox Code Playgroud)
我们可以通过声明变量是可选的来使编译器保持沉默:
@Input() userId?: string;
Run Code Online (Sandbox Code Playgroud)
但是,我们将不得不处理变量未定义的情况,并用一些这样的语句使源代码变得混乱:
if (this.userId) {
} else {
}
Run Code Online (Sandbox Code Playgroud)
相反,知道这个成员变量的值会及时定义,也就是说,它会在使用之前定义,我们可以告诉编译器不要担心它没有被定义。
告诉编译器这一点的方法是添加! definite assignment assertion
运算符,如下所示:
@Input() userId!: string;
Run Code Online (Sandbox Code Playgroud)
现在,编译器知道这个变量虽然没有在编译时定义,但应该在运行时定义,并且在使用它之前及时定义。
现在由应用程序确保该变量在使用之前已定义。
作为附加保护,我们可以在使用变量之前断言该变量已被定义。
我们可以断言变量已定义,即所需的输入绑定实际上是由调用上下文提供的:
private assertInputsProvided(): void {
if (!this.userId) {
throw (new Error("The required input [userId] was not provided"));
}
}
public ngOnInit(): void {
// Ensure the input bindings are actually provided at run-time
this.assertInputsProvided();
}
Run Code Online (Sandbox Code Playgroud)
知道变量已定义,现在可以使用该变量:
ngOnChanges() {
this.userService.get(this.userId)
.subscribe(user => {
this.update(user.confirmedEmail);
});
}
Run Code Online (Sandbox Code Playgroud)
请注意,ngOnInit
即使没有向绑定提供实际输入,该方法也会在输入绑定尝试之后调用。
而该ngOnChanges
方法在输入绑定尝试之后调用,并且仅当向绑定提供了实际输入时才调用。
Mar*_*uka 73
只需转到tsconfig.json并设置即可
"strictPropertyInitialization": false
Run Code Online (Sandbox Code Playgroud)
摆脱编译错误.
否则你需要初始化所有变量,这有点烦人
xgq*_*rms 47
\n\n演示代码
\n
class Plant {\n name: string;\n // \xe2\x9d\x8c Property \'name\' has no initializer and is not definitely assigned in the constructor.ts(2564)\n}\n
Run Code Online (Sandbox Code Playgroud)\nclass Plant {\n name: string | undefined;\n}\n
Run Code Online (Sandbox Code Playgroud)\nclass Plant {\n name!: string;\n}\n
Run Code Online (Sandbox Code Playgroud)\nclass Plant {\n name: string = \'\';\n}\n
Run Code Online (Sandbox Code Playgroud)\nclass Plant {\n name: string;\n constructor() {\n this.name = \'\';\n }\n}\n
Run Code Online (Sandbox Code Playgroud)\nclass Plant {\n name: string;\n constructor(name: string) {\n this.name = name ?? \'\';\n }\n}\n\n
Run Code Online (Sandbox Code Playgroud)\n5
class Plant {\n constructor(public name: string = name ?? \'\') {\n // \n }\n}\n\n
Run Code Online (Sandbox Code Playgroud)\n\n\n不建议
\n
{\n "compilerOptions": {\n+ "strictPropertyInitialization": false,\n- "strictPropertyInitialization": true,\n }\n}\n\n
Run Code Online (Sandbox Code Playgroud)\nhttps://www.typescriptlang.org/docs/handbook/2/classes.html#--strictpropertyinitialization
\ncri*_*ari 35
转到您的tsconfig.json
文件并进行更改, "noImplicitReturns": false
然后在属性下添加"strictPropertyInitialization": false
到您的tsconfig.json
文件中"compilerOptions"
。这是我的tsconfig.json
文件的样子
tsconfig.json
{
...
"compilerOptions": {
....
"noImplicitReturns": false,
....
"strictPropertyInitialization": false
},
"angularCompilerOptions": {
......
}
}
Run Code Online (Sandbox Code Playgroud)
希望这会有所帮助! 祝你好运
Saj*_*ran 27
我认为您使用的是最新版本的TypeScript.请参阅中的"严格类初始化"部分link
.
有两种方法可以解决这个问题:
答:如果您使用的是VSCode,则需要更改编辑器使用的TS版本.
B.只需在构造函数中声明数组时初始化数组,
makes: any[] = [];
constructor(private makeService: MakeService) {
// Initialization inside the constructor
this.makes = [];
}
Run Code Online (Sandbox Code Playgroud)
Har*_*ath 24
这是因为TypeScript 2.7包含一个严格的类检查,其中所有属性都应该在构造函数中初始化.解决方法是将!
后缀添加到变量名称:
makes!: any[];
Run Code Online (Sandbox Code Playgroud)
Ale*_*nic 24
该错误是合法的,可能会阻止您的应用程序崩溃。您输入的makes
是数组,但它也可以是未定义的。
您有 2 个选项(而不是禁用打字稿的存在原因...):
1.在您的情况下,最好输入makes
为可能未定义。
makes?: any[]
// or
makes: any[] | undefined
Run Code Online (Sandbox Code Playgroud)
因此,每当您尝试访问makes
它可能未定义时,编译器都会通知您。否则,如果以下// <-- Not ok
行在getMakes
完成之前执行或getMakes
失败,您的应用程序将崩溃并抛出运行时错误。那绝对不是你想要的。
makes[0] // <-- Not ok
makes.map(...) // <-- Not ok
if (makes) makes[0] // <-- Ok
makes?.[0] // <-- Ok
(makes ?? []).map(...) // <-- Ok
Run Code Online (Sandbox Code Playgroud)
2.你可以假设它永远不会失败,并且你永远不会在初始化之前尝试通过编写下面的代码来访问它(有风险!)。所以编译器不会关心它。
makes!: any[]
Run Code Online (Sandbox Code Playgroud)
Sum*_*mit 22
2021 年更新:
有像“strictPropertyInitialization”这样的属性
只需转到 tsconfig.json 并设置
“严格”:假
摆脱编译错误。
否则你需要初始化所有的变量,这有点烦人。
此错误背后的原因是:
小智 14
在make变量后加一个问号(?)。
makes?: any[];
vehicle = {};
constructor(private makeService: MakeService) { }
Run Code Online (Sandbox Code Playgroud)
现在应该可以了。我正在使用 Angular 12,它适用于我的代码。
小智 14
更好的方法是将感叹号添加到变量的末尾,您确定它不会是未定义的或空的,例如您正在使用需要从模板加载的 ElementRef ,并且不能在构造函数中定义,执行如下操作
class Component {
ViewChild('idname') variable! : ElementRef;
}
Run Code Online (Sandbox Code Playgroud)
sam*_*vic 14
如果您不想更改tsconfig.json,您可以这样定义您的类:
class Address{
street: string = ''
}
Run Code Online (Sandbox Code Playgroud)
或者,您也可以像这样继续:
class Address{
street!: string
}
Run Code Online (Sandbox Code Playgroud)
添加感叹号“!” 在变量名称之后,Typescript 将确保该变量不为 null 或未定义。
Joh*_*edy 11
从 TypeScript 2.7.2 开始,如果在声明时未分配属性,则需要在构造函数中初始化该属性。
如果您来自 Vue,则可以尝试以下操作:
添加"strictPropertyInitialization": true
到您的 tsconfig.json
如果您对禁用它不满意,您也可以试试这个makes: any[] | undefined
。这样做需要您使用空检查(?.
)运算符访问属性,即this.makes?.length
makes!: any[];
,这告诉 TS 将在运行时分配该值。M K*_*aei 10
在tsconfig.json文件中的“compilerOptions”内添加:
"strictPropertyInitialization": false,
Run Code Online (Sandbox Code Playgroud)
如果要基于接口初始化对象,可以使用以下语句将其初始化为空。
myObj: IMyObject = {} as IMyObject;
Run Code Online (Sandbox Code Playgroud)
小智 8
这是因为 Typescript 2.7.2 包含严格的类检查,所有属性都应在构造函数中声明。因此,要解决这个问题,只需添加一个感叹号 (!),例如:
name!:string;
Run Code Online (Sandbox Code Playgroud)
在我的 Angular 项目中添加 Node 时出现此错误 -
TS错误:?无法编译 TypeScript: (path)/base.api.ts:19:13 - 错误 TS2564:属性 'apiRoot Path' 没有初始值设定项,并且未在构造函数中明确分配。
私有 apiRootPath:字符串;
解决方案 -
添加"strictPropertyInitialization": false
在tsconfig.json 的'compilerOptions' 中。
我的package.json -
"dependencies": {
...
"@angular/common": "~10.1.3",
"@types/express": "^4.17.9",
"express": "^4.17.1",
...
}
Run Code Online (Sandbox Code Playgroud)
小智 7
新版本的打字稿引入了严格的类初始化,这意味着您需要在构造函数主体中初始化类中的所有属性,或者通过属性初始值设定项。在打字稿文档中检查它 以避免这种情况,您可以添加(!或?)属性
make!: any[] or make? : any[]
Run Code Online (Sandbox Code Playgroud)
否则,如果您希望在项目中永久删除严格的类检查,您可以在 tsconfig.json 文件中设置 strictPropertyInitialization": false
"compilerOptions": { .... "noImplicitReturns": false, .... "strictPropertyInitialization": false },
另一种修复变量必须保持未初始化(并且在运行时处理)的情况的方法是添加undefined
到类型(这实际上是 VC 代码建议的)。例子:
@Input() availableData: HierarchyItem[] | undefined;
@Input() checkableSettings: CheckableSettings | undefined;
Run Code Online (Sandbox Code Playgroud)
根据实际使用情况,这可能会导致其他问题,因此我认为最好的方法是尽可能初始化属性。
这已在 Angular Github 中进行了讨论,网址为https://github.com/angular/angular/issues/24571
我认为Angular 的推荐给出了很好的建议:
对于角度分量,请使用以下规则来决定:
a) 添加初始值设定项
b) 使字段可选?
c) 保留!
- 如果字段注释为
@input
- 使字段可选 b) 或添加初始值设定项 a)。- 如果组件用户需要输入 - 在
ngOnInit
c) 中添加断言并应用。- 如果该字段已注释
@ViewChild
,@ContentChild
- 将该字段设为可选 b)。- 如果该字段用
@ViewChildren
or注释@ContentChildren
- 添加回 '!' - C)。- 具有初始值设定项的字段,但它位于
ngOnInit
. - 将初始值设定项移至构造函数 a)。- 具有初始值设定项的字段,但它存在
ngOnInit
且无法移动,因为它依赖于其他@input
字段 - 添加回 '!' - C)。
小智 6
1)您可以像下面的代码一样应用它。当你这样做时,系统不会给出错误。
“明确赋值断言” (!)告诉 TypeScript 我们知道这个值
@Injectable()
export class Contact {
public name !:string;
public address!: Address;
public digital!: Digital[];
public phone!: Phone[];
}
Run Code Online (Sandbox Code Playgroud)
2)第二种方法是创建一个构造函数并在此处定义值。
export class Contact {
public name :string;
public address: Address;
public digital: Digital[];
public phone: Phone[];
constructor( _name :string,
_address: Address,
_digital: Digital[],
_phone: Phone[])
{
this.name=_name;
this.address=_address;
this.digital=_digital;
this.phone=_phone;
}
}
Run Code Online (Sandbox Code Playgroud)
3)第三种选择是创建一个 get 属性并分配一个值,如下所示
export class Contact {
public name :string="";
public address: Address=this._address;
get _address(): Address {
return new Address();
}
}
Run Code Online (Sandbox Code Playgroud)
小智 6
就我而言,它根据新的打字稿严格功能使用不同的声明:
@ViewChild(MatSort, {static: true}) sort!: MatSort;
Run Code Online (Sandbox Code Playgroud)
如果在 tsonfig.json 中禁用 typescript 新的严格功能
"compilerOptions": {
///
,
"strictPropertyInitialization":false
}
Run Code Online (Sandbox Code Playgroud)
旧的 Angular 的引导代码运行良好
@ViewChild(MatSort) sort: MatSort;
Run Code Online (Sandbox Code Playgroud)
感谢 Arunkumar Gudelli (2022),这里有 4 种解决问题的方法https://www.angularjswiki.com/angular/property-has-no-initializer-and-is-not-definitely-assigned-in-the-constructor /
您需要禁用--strictPropertyInitialization
Sajeetharan引用的,或者执行以下操作以满足初始化要求:
makes: any[] = [];
Run Code Online (Sandbox Code Playgroud)
小智 5
当您使用 typescript@2.9.2 升级时,它的编译器严格遵循在组件类构造函数中声明数组类型的规则。
要解决此问题,请更改代码中声明的代码或避免编译器在“tsconfig.json”文件中添加属性“strictPropertyInitialization”: false并再次运行 npm start 。
Angular Web 和移动应用程序开发,您可以访问 www.jtechweb.in
你不能只使用一个明确的赋值断言吗?(见https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#define-assignment-assertions)
即声明该属性为makes!: any[];
The !确保打字稿在运行时肯定会有一个值。
抱歉,我还没有在 angular 中尝试过这个,但是当我在 React 中遇到完全相同的问题时,它对我来说效果很好。
归档时间: |
|
查看次数: |
20926 次 |
最近记录: |