הגדרת משתנים ב angular 11
-
בס"ד
אני מגדיר משתנה כ class שיצרתי, והבנתי שבגרסאות האחרונות (אולי רק האחרונה), vsCode לא מסתפק רק במה שnגדירים את המשתנה כך:
sessionActive: TSession;
אלא הוא רוצה שגם יאתחלו אותו, כמו.
sessionsList: TSession[] = [];
או
sessionsList: TSession[] | undefined;
בנוגע לזה העדפתי להשתמש באפשרות השניה, בגלל שבאחד מהם אני רוצה לעשות בסוג {} ולא [],
א. האם יש אפשרות לאתחל אותו בצורה כזאת({})?ב. כשאני משתמש בו בhtml של קומפוננטה שאני מייבא את הSerive הזה, הוא כותב לי שגיאה.
הserivceimport { TSession } from '../../class/session'; @Injectable({ providedIn: 'root' }) export class SessionsService { sessionsList: TSession[] | undefined; sessionActive: TSession | undefined; constructor() {this.getSessionsListDemo() } getSessionsListDemo(){ this.sessionActive = { strSession: "sfganIshfunpuh493o892y49fymu43tr7nfg8fr2npeu45", userId: 4, userName: "XXX XXX", email: "XXX@chazondov.org", imgUrl: "http://localhost/img/user1.png", startDate: 1, lestDate: 1, countEntrys: 1 } this.sessionsList = [ { strSession: "sfganIOצקכ/ויyuip49fymu43tr7nfg8fr2npeu45", userId: 8, userName: "XXXX", email: "XXXX@gmail.com", imgUrl: "http://localhost/img/user.jpg", startDate: 1, lestDate: 1, countEntrys: 1 }, { strSession: "sfganIshfunpuh493o892y49fymu43tr7nfg8fr2npeu45", userId: 4, userName: "XXX XXX", email: "XXX@chazondov.org", imgUrl: "http://localhost/img/user1.png", startDate: 1, lestDate: 1, countEntrys: 1 }, { strSession: "sfganIshfunpuh493o892y49fymu43tr7nfg8fr2npeu45", userId: 2, userName: "XXX XXX XXXX", email: "XXXX@gmail.com", imgUrl: "http://localhost/img/user2.jpg", startDate: 1, lestDate: 1, countEntrys: 1 } ] console.log(this.sessionsList) } }
בקומפוננטה ts
import { SessionsService } from '../../../sys/services/user/sessions.service'; constructor(public sessionsService: SessionsService) {}
בקומפוננטה בhtml
<span #TitleUsrName class="mx-1" [ngClass]="{'d-none':settings.smWidth === true}" [matMenuTriggerFor]="userMenu">{{sessionsService.sessionActive.userName}}</span> <img [src]="sessionsService.sessionActive.imgUrl" class="rounded-circle" width="35" height="35" alt="">
זה עובד, אבל מראה לי שגיאה.
תודה רבה וסליחה על האריכות
מקווה שזה מספיק ברור ומספיק נתונים
השתדלתי כמה שיותר לתעד, כמו שמבקש @dovid -
הנושא פה הוא TypeScript ולא אנגולר.
כשאתה כותב כזה דבר:sessionActive: TSession;
השגיאה היא:
Property 'sessionActive' has no initializer and is not definitely assigned in the constructor.(2564)
תרגום: המאפיין לא מאותחל (לא קבעו לו ערך ראשוני) בבנאי (הקונסטרקטור של המחלקה)
ולחילופין לא שמו לו מאתחל שנקרא initializer שזה בדיוק מה שהראית בדוגמא השניה (רק שהראית את זה על מערך).
בא נשים initializer:sessionActive: TSession = new TSession();
רוצה שבינתיים לא יהיה בו כלום? אז תאפשר שיהיה בו null על ידי סימן שאלה אחרי שם המשתנה ככה:
sessionActive?: TSession;
רק מה? שבעצם הכרזת ש"לא בטוח שיש שמה משהו" וזה ירדוף קצת אחריך, כל התייחסות בקוד:
console.log(this.sessionActive.val);
תזכה בשגיאה כזאת: Object is possibly 'undefined'.(2532)
בינינו, הוא הרי צודק אבל הוא חופר!
תוכל להגיד לו שאתה רוצה את הערך val רק אם sessionActive מכיל אובייקט, ע"י סימן שאלה לפני גישה למאפיין, ככה:console.log(this.sessionActive?.val);
בעצם מה שקורה פה זה מאוד פשוט, TypeScript רוצה שיהיה ביטחון מוחלט מה הולך להיות בלי לבנות ולא משפט סתמי של "אני אדאג לאתחל אותו". זה הראש של תכנות עם טיפוסיות קשוחה, וצריך להתרגל לתכנן בהתאם.
בקשר ל[] ול{}. הראשון זה מערך, והשני זה איבר בודד בדיוק כמו מספר או טקסט, אבל מסוג אובייקט.
בTypeScript כשאתה שם [] למערך הוא מבין שזה מערך ריק, מהסוג עליו אנו עוסקים. אולם כשמדובר באובייקט אז אני לא יודע אילך ההתייחסות ל{}, מה שבטוח שיותר מפורש זה = new TSession(); -
אני צריך להוסיף שתי דברים:
א. מה שכתבתי נכון כשהשפה מוגדרת על strictNullChecks שזה אומר שכל טיפוס שלא נאמר מפורש שיכול להכיל null אז אסור לו להכיל null, ולכן חייב להיות אתחול. זה הסיבה שזה חדש אצלך, עד היום עבדת עם גרסאות קודמות כנראה של TypeScript.
ב. מה שהזכרת שאפשר לכתוב TSession | undefined נכון לגמרי, זה בעצם אומר שאתה כן מרשה שיהיה משתנה לא מאותחל, אני לא הבנתי מה זה שונה מטיפוס nullable שהזכרתי עם הסימן שאלה.בקיצור אני לא יודע TypeScript אבל אולי יבוא מישהו וישלים את החסרים שלי.
-
@avi-rz בקשר לשגיאות בייבוא יש לך שתי אפשרויות, או לישם סימני שאלה בשימוש בhtml לפני כל נקודה שניגשת למאפיין של מאפיין שלא בטוח קיים, או לבטל את ה | undefined ולדאוג שהתכנון יבטיח אתחול בבנאי או עוד קודם לכן (אתחול באובייקט ריק בד"כ זה בריחה מהתכנון הנכון, אבל זה יעבוד).
-
@dovid תודה רבה.
@dovid אמר בהגדרת משתנים ב angular 11:
רק מה? שבעצם הכרזת ש"לא בטוח שיש שמה משהו" וזה ירדוף קצת אחריך, כל התייחסות בקוד:
console.log(this.sessionActive.val);תזכה בשגיאה כזאת: Object is possibly 'undefined'.(2532)
בינינו, הוא הרי צודק אבל הוא חופר!
תוכל להגיד לו שאתה רוצה את הערך val רק אם sessionActive מכיל אובייקט, ע"י סימן שאלה לפני גישה למאפיין, ככה:
console.log(this.sessionActive?.val);אכן ניסיתי גם לעשות ? לפני המשתנה המפוקפק,
אבל לא עלה בידי יפה,
למשל כשבאתי לבדוק if מול נתון דומה.אני יבדוק בהמשך עוד הפעם, אולי באמת פיספתי משהו.
-
@dovid אמר בהגדרת משתנים ב angular 11:
sessionActive: TSession = new TSession();
ע"ז יש שגיאה:
error TS2693: 'TSession' only refers to a type, but is being used as a value here.
@avi-rz אמר בהגדרת משתנים ב angular 11:
אכן ניסיתי גם לעשות ? לפני המשתנה המפוקפק,
אבל לא עלה בידי יפה,
למשל כשבאתי לבדוק if מול נתון דומה.
אני יבדוק בהמשך עוד הפעם, אולי באמת פיספתי משהו.בדקתי,
זה הקוד.<mat-card *ngIf="!session.userId === this.sessionsService.sessionActive?.userId" class="example-container rounded-pill my-2">
אני מקבל את השגיאה
error TS2367: This condition will always return 'false' since the types 'boolean' and 'TSession | undefined' have no overlap.
אני כרגע משתמש בפונקציה.
בtsgetIsSessionActive(session: TSession): boolean{ if (session.userId === this.sessionsService.sessionActive?.userId) { return true } else { return false } }
בhtml
<mat-card *ngIf="!getIsSessionActive(session)" class="example-container rounded-pill my-2">
אבל בדרך הזו אני לא יתעדכן, בגלל שאני לא שואב את הנתון ישר מהsrvice אלא מהפונקציה, והיא מופעלת רק בהתחלה.
עריכה: מה שמעניין, שכשאני משתמש באופציה הראשונה אם ה? לפני המשתנה המפוקפק, הוא נותן לי להשתמש אם אני עושה אותו כתנאי של true, אבל כשאני מוסיף לו את ה "!" בשביל להפוך אותו לתנאי שלילה אז מופיעה לי השגיאה.
-
סליחה על ההטרדה, כנראה היה חסר לי משהו בבסיס.
@avi-rz אמר בהגדרת משתנים ב angular 11:
עריכה: מה שמעניין, שכשאני משתמש באופציה הראשונה אם ה? לפני המשתנה המפוקפק, הוא נותן לי להשתמש אם אני עושה אותו כתנאי של true, אבל כשאני מוסיף לו את ה "!" בשביל להפוך אותו לתנאי שלילה אז מופיעה לי השגיאה.
הכנסתי את התנאי הנ"ל בתוך סוגריים עם ה"!" לפני וזה עזר.
-
@avi-rz זה אכן בדיוק מה שכתוב בשגיאה:
error TS2367: This condition will always return 'false' since the types 'boolean' and 'TSession | undefined' have no overlap.
בסדר הקדימות, השלילה של ! קודמת להשוואה. אז מה שמושווה זה התוצאה של !session.userId (שהיא כן/לא) מול הuserId שהוא מספר.אגב במקום לשים סוגריים במקרה הזה אפשר לכתוב !== במקום === עם שלילה.