Skip to content

Every field is optional in generated types #4

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
stpoa opened this issue May 25, 2023 · 9 comments
Open

Every field is optional in generated types #4

stpoa opened this issue May 25, 2023 · 9 comments

Comments

@stpoa
Copy link

stpoa commented May 25, 2023

Every field is optional in generated types regardless of settings in Directus.

Any idea why?

@aurelienbobenrieth
Copy link

Yeah was wondering the same, this is pretty annoying.

@Anoesj
Copy link

Anoesj commented Aug 4, 2023

I agree it's annoying. However, this is a problem (or decision) on either Directus' end or in the openapi-typescript module. All this module does is fetch Directus' OpenAPI spec and turn it into TS definitions using openapi-typescript. There's not a lot of magic or type transformation going on in this module itself.

@sunxyw
Copy link

sunxyw commented Oct 15, 2023

Because Directus allows you to modify the fields to be retrieved using the fields parameter, not every field will be returned.

@HarunKilic
Copy link

Did you guys find any workaround? Or did you find another solution?

@sunxyw
Copy link

sunxyw commented Nov 17, 2023

Did you guys find any workaround? Or did you find another solution?

you may try setting the field to not null, and see if it helps

@HarunKilic
Copy link

Did you guys find any workaround? Or did you find another solution?

you may try setting the field to not null, and see if it helps

Even ID seems to be optional. But I'll give it a try.

@Frioo
Copy link

Frioo commented May 12, 2024

Wondering if there's any updates on this.
Also a little off-topic, but anyone got a clue how to get properly typed responses for relational fields?
Let's say I have a collection like this:

interface Products {
  id?: number;
  title?: string | null
  media?: number | MyMediaItem[] | null
}

where MyMediaItem is the related collection item type. When fetching with fields: ['*"] media should be of type number, but with fields: ["*", "media.*"] I should get MyMediaItem[]. This does not seem to work, and I can't have typing/intellisense for the related item since for typescript it's always number | MyMediaItem[] | null. Quite annyoing, not sure how to tell TS/Directus SDK that it should force one of the available types for a specific query.

@Bijig0
Copy link

Bijig0 commented May 13, 2024

Wondering if there's any updates on this. Also a little off-topic, but anyone got a clue how to get properly typed responses for relational fields? Let's say I have a collection like this:

interface Products {
  id?: number;
  title?: string | null
  media?: number | MyMediaItem[] | null
}

where MyMediaItem is the related collection item type. When fetching with fields: ['*"] media should be of type number, but with fields: ["*", "media.*"] I should get MyMediaItem[]. This does not seem to work, and I can't have typing/intellisense for the related item since for typescript it's always number | MyMediaItem[] | null. Quite annyoing, not sure how to tell TS/Directus SDK that it should force one of the available types for a specific query.

Same brother, same...

@pomeh
Copy link

pomeh commented Jun 3, 2024

Hello,

I encounter the same problem, and here are some informations that may help (or not).

First, the OpenAPI spec (OAS) from Directus (/server/specs/oas) does not list which fields are required or not. If OAS don't know it, the spec for /items/whatever/{id} operation JSON response is converted into a TS type with properties as optionnals. But having a field required in Directus only concern the item creation and edition, if you have older items before field foo became required, the field may still be inexistent.

Second, for a given endpoint (for example /items/whatever/{id}), one may decide to include only some fields in the JSON output (directus.request(readItems('whatever', {fields: ["bar"]}))), so even if field foo is required for all items in the collection, this call will only return the bar field. The typings for directus.request and/or readItems could be updated to create a new Type based on which fields are listed, but I guess this needs a fix inside Directus code.

Lastly, even if you include fields * in your REST request, an admin can configure endpoints to retrict which fields are public or not. So the typings used must reflect the correct permissions you have when requesting the API endpoints. If you use the API anonymously, the typings must be the public /server/specs/oas. If you use it with a specific role, typings must be ajusted.

Concerning to composed type problem, one ugly workaround I found so far is to use TypeScript type guards. For example:

function hasAuthor(user?: components["schemas"]["whatever"]["user_created"]): user is components["schemas"]["Users"] {
	return user !== undefined && user !== null && typeof user === 'object' && 'first_name' in user;
}

export default async function MyPage() {
	const whatevers = await directus.request(
		readItems('whatever', {
			fields: ["foo", { "user_created": ["first_name"]}],
		})
	);

	return (
		<div>
			{whatevers.map((whatever) => {
				return (
					<span key={whatever.id}>{hasAuthor(whatever.user_created) && whatever.user_created.first_name}</span>
				);
			})}
		</div>
	);
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants