-
Notifications
You must be signed in to change notification settings - Fork 465
genType: treat option<t> as t | undefined and remove special treatment of record fields of option type. #6022
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
Conversation
This produces strictly fewer conversion functions, as it does not need to transform `null` to `undefined`.
f5a3583
to
83404c1
Compare
This is a breaking changes, but aligns more closely with TS. The two TS types: ```ts type t1 = { x?: string }; type t2 = { x: (undefined | string) }; ``` now correspond to the ReScript types: ```res @genType type t1 = {x?: string} @genType type t2 = {x: Js.undefined<string>} ``` The special treatment of fields of option type comes from a time where records with optional fields did not exist.
Added examples. TS functions: // CoreTS.ts
export declare function someFunWithNullThenOptionalArgs(
nullable: null | string,
app?: string
): string;
export declare function someFunWithNullUndefinedArg(
nullUndefined: null | undefined | string,
other: number
): string; ReScript bindings: @genType.import("./CoreTS")
external someFunWithNullThenOptionalArgs: (
Null.t<string> /* Cannot be Nullable.t or option */,
option<string> /* Cannot be Null.t or Nullable.t */,
) => string = "someFunWithNullThenOptionalArgs"
@genType.import("./CoreTS")
external someFunWithNullUndefinedArg: (
Nullable.t<string> /* Can also be Null.t or option as they are subtypes */,
int,
) => string = "someFunWithNullUndefinedArg" Notice that out of the 3 choices: |
Complete bindings for one firebase function (CC @jmagaram): type firebaseOptions = {
apiKey?: string,
authDomain?: string,
databaseURL?: string,
projectId?: string,
storageBucket?: string,
messagingSenderId?: string,
appId?: string,
measurementId?: string,
}
type firebaseApp = {
name: string,
options: firebaseOptions,
automaticDataCollectionEnabled: bool,
}
type analytics = {app: firebaseApp}
type analyticsCallOptions = {global: bool}
@genType.import("firebase/analytics")
external setUserId: (analytics, Null.t<string>, option<analyticsCallOptions>) => unit = "setUserId" gives /* TypeScript file generated from Core.res by genType. */
/* eslint-disable import/first */
import {setUserId as setUserIdNotChecked} from 'firebase/analytics';
// In case of type error, check the type of 'setUserId' in 'Core.res' and 'firebase/analytics'.
export const setUserIdTypeChecked: (_1:analytics, _2:(null | string), _3:(undefined | analyticsCallOptions)) => void = setUserIdNotChecked;
// Export 'setUserId' early to allow circular import from the '.bs.js' file.
export const setUserId: unknown = setUserIdTypeChecked as (_1:analytics, _2:(null | string), _3:(undefined | analyticsCallOptions)) => void;
// tslint:disable-next-line:interface-over-type-literal
export type firebaseOptions = {
readonly apiKey?: string;
readonly authDomain?: string;
readonly databaseURL?: string;
readonly projectId?: string;
readonly storageBucket?: string;
readonly messagingSenderId?: string;
readonly appId?: string;
readonly measurementId?: string
};
// tslint:disable-next-line:interface-over-type-literal
export type firebaseApp = {
readonly name: string;
readonly options: firebaseOptions;
readonly automaticDataCollectionEnabled: boolean
};
// tslint:disable-next-line:interface-over-type-literal
export type analytics = { readonly app: firebaseApp };
// tslint:disable-next-line:interface-over-type-literal
export type analyticsCallOptions = { readonly global: boolean }; |
Can be used to bind to functions with optional parameters, using
option
.Before:
option<t>
maps to this TSnull | undefined | t
Now:
option<t>
maps to this TSundefined | t
Before:
{x:option<string>}
maps to this TS{x?: string}
.Now:
{x:option<string>}
maps to this TS{x: (undefined | string)}
(same for{x:Js.undefined<string>}
)Unchanged:
{x?: string}
maps to this TS{x?: string}
.This also produces strictly fewer conversion functions, as it does not need to transform
null
toundefined
.