Reputation: 51
I have data coming in from an API in a Vue 3 Typescript code base. While the data is in transit, I want to know that it's missing. Currently, this is how I do it:
data() {
return {
apiData: null as DataType | null
}
},
async mounted() {
this.apiData = await getData()
}
The issue is defining the type of apiData: null as DataType | null
is cumbersome and just feels wrong. I haven't seen any examples of how to do that properly besides a cast like that.
Is there a better way to mark a property of an object as an optional type? I know about interfaces but my objects is a very complex type and that optional data is only one property of it...
Thanks for the help!
Upvotes: 4
Views: 3720
Reputation: 95614
This is likely the best you can get, as on the Data Properties and Methods v3 guide:
These [data] instance properties are only added when the instance is first created, so you need to ensure they are all present in the object returned by the data function. Where necessary, use null, undefined or some other placeholder value for properties where the desired value isn't yet available.
If you'd like to make the definition less cumbersome, you could always define a utility like opt<T>() => undefined as T | undefined
or type Opt<T> = T | undefined
.
data() {
function opt<T>() { return undefined as T | undefined; }
return {
apiData: opt<DataType>(),
foo: opt<Bar>(),
}
},
async mounted() {
this.apiData = await getData()
}
That said, if you're willing to add one other layer of indirection, you could install your optional properties on a Partial<YourData>
instance that you hold in your data
object. Because Vue can proxy "deep" nested property access, this should give Vue the chance to react to the addition/deletion of more properties without having to define them up front.
interface OptionalData {
prop1: string;
prop2: number;
apiData: DataType;
}
data() {
return {
optionalData: {} as Partial<OptionalData>
}
},
async mounted() {
this.optionalData.apiData = await getData()
}
Of course, your component may become difficult to understand if you have to react to the presence or absence of many optional fields. If you're finding you need this pattern often, it may indicate an opportunity to refactor your component into multiple smaller components or create a richer model object that can abstract away some of the complexity.
Upvotes: 2