React转TypeScript时右手边类型赋值问题:能否为不同类型的赋值结果分别指定类型?
Hey there! Let's tackle this problem you're facing while migrating your React app to TypeScript.
First off, the syntax you're hoping for—const day = days?.find(d => isSameDate(d.date, date)):Iday || {}:Iempty;—isn't supported in TypeScript. You can't annotate types directly on individual branches of an expression like that. But don't worry, there are several clean ways to achieve the behavior you want.
Why Your Original Code Throws an Error
Let's start by understanding why TypeScript is complaining. When you write:
const day: Iday = days?.find(d => isSameDate(d.date, date)) || {};
days?.find(...)returns either anIday(if a match is found) orundefined(if no match exists ordaysisundefined).- The
|| {}replacesundefinedwith an empty object, so the final type ofdaybecomesIday | {}instead of justIday. TypeScript correctly flags that accessingday.datemight fail because the empty object doesn't have adateproperty.
Solutions to Fix the Issue
1. Use Type Guards to Handle the "No Match" Case
If the empty object is meant to signal "no matching day found", you can split the logic and use a type guard to safely access properties when a match exists:
const day = days?.find(d => isSameDate(d.date, date)); if (day) { // TypeScript knows `day` is an Iday here—safe to access day.date! console.log(day.date); } else { // Handle the "no day found" scenario here (e.g., show a message, use defaults) }
2. Provide a Default Value That Matches the Iday Type
If you need day to always be an Iday (even when no match is found), create a default Iday object instead of using an empty object:
interface Iday { date: Date; // Add other properties your interface defines } // Define a valid default Iday (adjust properties to match your interface) const defaultEmptyDay: Iday = { date: new Date(0), // Or use a placeholder date value // Set default values for other properties if needed }; const day: Iday = days?.find(d => isSameDate(d.date, date)) || defaultEmptyDay; // Now you can safely access day.date without errors
3. Use a Union Type + Type Guard for Explicit Empty Object Handling
If you must keep the empty object as a valid case, define a union type and use a type guard to distinguish between the two cases:
type DayResult = Iday | {}; const day: DayResult = days?.find(d => isSameDate(d.date, date)) || {}; // Use a type guard to check if we have a valid Iday function isIday(value: DayResult): value is Iday { return 'date' in value; } if (isIday(day)) { // Safe to access day.date here console.log(day.date); } else { // Handle the empty object case }
Final Notes
TypeScript's strictness here is helping you avoid potential runtime errors (like trying to access date on an empty object). While you can't annotate individual expression branches directly, the above approaches let you handle both cases safely while keeping TypeScript happy.
内容的提问来源于stack exchange,提问作者Matyno

