You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// From hack-json-schema/src/BaseValidator.phpinterfaceValidator<+T> {
publicfunctionvalidate(): void;
publicfunctionisValid(): bool;
publicfunctiongetErrors(): vec<TFieldError>;
publicfunctiongetValidatedInput(): ?T;
// ^^ nullable T
}
abstractclassBaseValidator<+T> implementsValidator<T> {
//...finalpublicfunctiongetValidatedInput(): T {
//... ^ non-nullable T
}
}
Let's say we want to make an API that can either be used using runtime typechecking (using a json schema) or by trusting the typechecker, in cases where the performance of validating a bajillion-element array is not feasible.
usenamespace Our\Json;
usenamespace Slack\Hack\JsonSchema;
classOptionallyTypedAPI<T> {
publicfunction__construct(
private (function(mixed): JsonSchema\Validator<T>) $validator_function
) {}
publicfunctiontrustTheTypesystem(T$argument): void {
echojson_encode($argument);
}
publicfunctionuseTheValidator(mixed$argument): void {
$validator= ($this->validator_function)($argument);
$validator->validate();
if (!$validator->isValid()) {
thrownewTypeError("some runtime message");
}
echojson_encode($argument);
}
}
<<__EntryPoint>>
asyncfunctionmain_api_design_rfc_async(): Awaitable<void> {
// $foo is not OptionallyTypedAPI<shape('success' => bool)>$foo=newOptionallyTypedAPI($json==>newOur\SuccessBoolSchema($json));
// $foo now becomes OptionallyTypedAPI<(shape('success' => bool) | darray<int, int>)>// depending on the type inference of your hh_client.// I think Slack's hh_client will actually use Unresolved[...] instead, but don't quote me on that.$foo->trustTheTypesystem([5=>5]); // This is fine!?
}
You will quickly run into the situation where the contravariance-ness of Validator means that hh_client will just make your OptionallyTypedAPI<T> into OptionallyTypedAPI<some_super_type_or_mixed>.
I would like to discuss adding another interface which solves these two issues in one go.
This would prevent the typechecker from generalizing your API, since it must use the exact type of T in: private (function(mixed): JsonSchema\InvariantValidator<T>) $validator_function
And as a bonus, I can make getValidatedInput() return T instead of ?T, without breaking BC.
We could add an implements JsonSchema\InvariantValidator<TYourCurrentSchema> to the generated classes. This would not prevent you from doing contravariant things if you refer to them as Validator<T> or BaseValidator<T>.
I would love to get some feedback on this.
The text was updated successfully, but these errors were encountered:
The Validator interface returning ?T is an oversight. We used to return ?T if you called getValidatedInput and it hadn't been validated, but it was annoying to have to cast that to nonnull so we added throwing the exception if you tried to access the value before calling validate. I think I just forgot to update the interface.
Let's say we want to make an API that can either be used using runtime typechecking (using a json schema) or by trusting the typechecker, in cases where the performance of validating a bajillion-element array is not feasible.
You will quickly run into the situation where the contravariance-ness of Validator means that hh_client will just make your
OptionallyTypedAPI<T>
intoOptionallyTypedAPI<some_super_type_or_mixed>
.I would like to discuss adding another interface which solves these two issues in one go.
This would prevent the typechecker from generalizing your API, since it must use the exact type of
T
in:private (function(mixed): JsonSchema\InvariantValidator<T>) $validator_function
And as a bonus, I can make
getValidatedInput()
returnT
instead of?T
, without breaking BC.We could add an
implements JsonSchema\InvariantValidator<TYourCurrentSchema>
to the generated classes. This would not prevent you from doing contravariant things if you refer to them asValidator<T>
orBaseValidator<T>
.I would love to get some feedback on this.
The text was updated successfully, but these errors were encountered: