faker
faker copied to clipboard
Introduce a way to get details about missing locale data when using them
Clear and concise description of the problem
Currently many methods look like this:
foobar(): string {
return this.faker.random.arrayElement(this.faker.definitions.foo.bar);
}
However, the current locale does not have a value for it, then it will return 'a' | 'b' | 'c'
.
It would be nice, if the method would throw an error, with details about missing data.
It should still be possible to check whether the data exists without throwing and catching an error.
This kind of blocks the removal of the default from random.arrayElement()
Suggested solution
Change the faker.definitions
to throw an error, if the data are absent.
Introduce faker.extensions
that would return undefined (the current faker.definitions
behavior).
(Not sure about the name)
Alternative
Check the data before using it each time. This reduces the code readability a lot.
Additional context
IMO faker.definitions
should change its behavior, instead of adding a new field for it, because I assume, the default expectation is that the data are present. Most of our methods wouldn't change either. Only some of them would, where the data are explicitly optional.
Just to prioritize some issues, I would see
- https://github.com/faker-js/faker/issues/823
should be handled before this issue
We might also need a way to mark/handle explicitly missing data. https://github.com/faker-js/faker/pull/1665#discussion_r1048345332 introduces empty arrays for that purpose.
Team decision
If faker.definitions.category.entry is not defined we will throw an error.
What blocks us from "simply" making all definitions required? If we currently don't have any they could be filled with an empty array. Then the next step would be to throw an error in helpers.arrayElement
when an empty array is passed.
Is that the desired behavior or did I misunderstood the issue?
The current behavior is to fallback to the fallback locale ie English en which is defined for nearly everything.
In which cases would we want to explicitly throw an error?
The current behavior is to fallback to the fallback locale ie English en which is defined for nearly everything.
Yes, that is correct. But this happens when accessing the actual locale data via the Proxy
:
https://github.com/faker-js/faker/blob/f9e5ba706aa23ce958b9f82b09814a98ce830515/src/faker.ts#L191-L196
Which could simply be replaced by checking against the entries
length instead of its existence.
In which cases would we want to explicitly throw an error?
I'm talking about two different things here (locale data accessing and helpers.arrayElement
behavior). I'm currently more focused on throwing an error in helpers.arrayElement
if an empty array is passed as a parameter.
What blocks us from "simply" making all definitions required?
Currently only:
- https://github.com/faker-js/faker/blob/f9e5ba706aa23ce958b9f82b09814a98ce830515/src/modules/location/index.ts#L95 (to be made required in https://github.com/faker-js/faker/pull/1760)
But we have a PR that adds more:
If we currently don't have any they could be filled with an empty array.
There are three problems with that.
- We would have to check that in each method and would have to throw an easy to understand error message.
- Thus reducing the readability of the implementation
- Or loosing DX if we just let that empty array wander over to
helpers.arrayElement
- We are likely to miss adding [] for new/other locales for these required values
- We will likely bloat our locales with "empty" files
- We cannot safely add this via Proxy because of 3
- We loose the ability to distinguish between missing/not yet provided data and explicitly unsupported/unavailable data
- Not all our locale data are arrays, some are objects (e.g.
location.postcode_by_state
), some might be singular data (locale title, locale code, ...)
Then the next step would be to throw an error in helpers.arrayElement when an empty array is passed.
This issue is explictly about improving the DX by exposing which data are missing:
new FakerError("This faker instance does not have any data for ``location.postcode_by_state``. Please make sure you configured the correct fallbacks or create a PR that adds these data to Faker for your locale.");
instead of:
new FakerError("Cannot invoke helpers.arrayElement() with an empty array")
The current behavior is to fallback to the fallback locale ie English en which is defined for nearly everything.
In which cases would we want to explicitly throw an error?
In the case where you don't want the English fallback and you explicitly want only data in your selected locale. (You will then get an explicit error, requesting you to provide the data, instead of silently falling back to English values)
The current behavior is to fallback to the fallback locale ie English en which is defined for nearly everything.
Yes, that is correct. But this happens when accessing the actual locale data via the
Proxy
:
Which IMO is likely to change in implementation, but will still be some kind of Proxy (to throw useful error messages).
Which could simply be replaced by checking against the entries length instead of its existence.
See https://github.com/faker-js/faker/issues/893#issuecomment-1429689500 (1. argument)
I'm currently more focused on throwing an error in
helpers.arrayElement
if an empty array is passed as a parameter.
Which is a different issue altogether: #219
Ok so this this mostly a internal issue
For most consumers of the library nothing much changes unless you are explicitly not falling back to en (which requires a non-default setup) or using one of the rare methods which don't have a en fallback?
Note to self: Do it.
I have to create a PR for moving definitions.title
to definitions.metadata.title
first.
Blocked by #1978.
- #1978
I've been thinking about this, and perhaps this could be an explicit option on the Faker instance, because in some cases you might want an error, and in some cases e.g. if you are directly using calls to Faker in templates, you would rather just have undefined returned.
Suppose you have a method which is only defined in certain locales (say faker.location.county()
because not all countries have 2nd lebel admin areas, or faker.person.prefix()
, because not all languages use prefixes in names.
Then you could do
fakerXX.location.county() // undefined
fakerXX.throwsErrorOnMissingData = true
fakerXX.location.county() // throws '"This faker instance does not have any data for `location.county`. Please make sure you configured the correct fallbacks or create a PR that adds these data to Faker for your locale.'
Team Decision
fakerXX.throwsErrorOnMissingData = true
While this is an interesting feature, it is not possible to implement this in a type safe way.
If we add | undefined
to every method then all our users would have to use !
when generating values, which will likely cause lint warnings.
If we don't add it, then we violate TS types.
There might be ways to handle that using some kind of Faker type overwrite. However that will probably break with our tree shakign efforts in v8.2. So we won't implement this for now.
Team Decision
fakerXX.throwsErrorOnMissingData = true
While this is an interesting feature, it is not possible to implement this in a type safe way.
If we add
| undefined
to every method then all our users would have to use!
when generating values, which will likely cause lint warnings.If we don't add it, then we violate TS types.
There might be ways to handle that using some kind of Faker type overwrite.
However that will probably break with our tree shakign efforts in v8.2.
So we won't implement this for now.
That's why JavaScript is better than typescript 😂😂😂
Team Decision
We want this for v8.0.