[Canvas] Add Types to Functions#35087
Conversation
|
Pinging @elastic/kibana-canvas |
💔 Build Failed |
Not sure I'm understanding correctly, but does this mean things like
|
|
@lukasolson Nice catch. @w33ble can you explain the relationship between |
💔 Build Failed |
|
Is there a reason you defined the type as Seems like it would fit better if you did context than arguments, since that's the order of the arguments in |
|
@w33ble I can change the order, but you'd be forced to add |
|
@w33ble For example: would become |
💔 Build Failed |
aafca71 to
778e592
Compare
💔 Build Failed |
|
@clintandrewhall I think |
778e592 to
622e56b
Compare
|
As requested, I've updated this PR to only include the TS changes. I'm still making some changes around naming. |
💔 Build Failed |
💔 Build Failed |
💔 Build Failed |
💔 Build Failed |
| /** | ||
| * Utility type: gathers values of a collection as a type for use as a type. | ||
| */ | ||
| export type ValuesOf<T extends any[]> = T[number]; |
There was a problem hiding this comment.
TS ramp-up (for me) question, what's the difference between this and eg. Array<T>?
There was a problem hiding this comment.
You should only use Array<T> for complex type expressions, (and eslint will complain if you deviate). For example: string[] and FooType[] are preferable to Array<string> or Array<FooType>, but Array<{foo: string}> is preferable in that case.
There was a problem hiding this comment.
I read it - correctly? - as:
- "You should use Array for complex type expressions only" (ie. not for simple expressions, though I'm not yet clear on what constitutes simple vs complex)
string[]andFooType[]are semantically, but not stylistically equivalent toArray<string>andArray<FooType>, resp.
I tried to trigger the syntax check, entering
export type ValuesOf<T extends any[]> = Array<T>;
but it didn't balk, maybe it still accepts it or I don't run the right linter. Also, ValuesOf and UnionToIntersection seem to be unused atm. All these are only curiosities, not sure if they're important at all.
There was a problem hiding this comment.
I think generics may be an exception...?
| */ | ||
| // prettier-ignore | ||
| export type AvailableFunctionNames = | ||
| AvailableFunctions<typeof commonFunctions[number]>['name'] & |
There was a problem hiding this comment.
First of all, incredible work, learning so much just by looking through this! How can AvailableFunctionNames be used? It's not being referred to now, does it have an impact without use, or if not, what can in theory be hooked up to it?
There was a problem hiding this comment.
This is going to be used for i18n, for starters. You'll see it's usefulness in my next diff.
There was a problem hiding this comment.
Here's a practical example. In this case, the AvailableFunctions type can be used to enforce the structure of the FunctionHelpDict type, throwing a TS error if any of the functions are missing.
/** This type uses the collection of available functions, (which are all
* `FunctionFactory`), to derive the name and argument types from them. This
* allows for validation that 1/ every function available is listed, and 2/ every
* function argument has a help string present.
*/
type FunctionHelp<T> = T extends FunctionFactory<
infer Name,
infer Context,
infer Arguments
>
? {
[key in Name]: {
help: string;
args: { [key in keyof Arguments]: string };
}
}
: never;
/**
* This type represents an exhaustive dictionary of Function help strings,
* organized by Function and then Function Argument.
*
* This type indexes the existing function factories, reverses the union to an
* intersection, and produces the dictionary of strings.
*/
type FunctionHelpDict = UnionToIntersection<FunctionHelp<typeof functions[number]>>;
/**
* Help text for Canvas Functions should be properly localized. This function will
* return a dictionary of help strings, organized by Canvas Function specification
* and then by available arguments.
*/
export const getFunctionHelp = (): FunctionHelpDict => {
return {
alterColumn: {
help: i18n.translate('xpack.canvas.functions.alterColumnHelpText', {
defaultMessage:
'Converts between core types, eg string, number, null, boolean, date and rename columns',
}),
args: {
column: i18n.translate('xpack.canvas.functions.alterColumn.args.columnHelpText', {
defaultMessage: 'The name of the column to alter',
}),
type: i18n.translate('xpack.canvas.functions.alterColumn.args.typeHelpText', {
defaultMessage: 'The type to convert the column to. Leave blank to not change type',
}),
name: i18n.translate('xpack.canvas.functions.alterColumn.args.nameHelpText', {
defaultMessage: 'The resultant column name. Leave blank to not rename',
}),
},
},
💔 Build Failed |
💚 Build Succeeded |
monfera
left a comment
There was a problem hiding this comment.
Incredible, tight fitting types PR!
monfera
left a comment
There was a problem hiding this comment.
Thanks @clintandrewhall, I learnt a ton from this PR and there's still much to absorb!
💔 Build Failed |
💚 Build Succeeded |
* Reducing changeset to TS-only * Update names; fix a few bugs * Test fixes * Add browser and server functions * Update ts-ignore comments; convert pie; break up TS defs * Convert const to func * Plot conversion * Tweaks to documentation * Fix deleted file * Fix type errors * Update yarn.lock * Address feedback
* Reducing changeset to TS-only * Update names; fix a few bugs * Test fixes * Add browser and server functions * Update ts-ignore comments; convert pie; break up TS defs * Convert const to func * Plot conversion * Tweaks to documentation * Fix deleted file * Fix type errors * Update yarn.lock * Address feedback
💔 Build Failed |
* Reducing changeset to TS-only * Update names; fix a few bugs * Test fixes * Add browser and server functions * Update ts-ignore comments; convert pie; break up TS defs * Convert const to func * Plot conversion * Tweaks to documentation * Fix deleted file * Fix type errors * Update yarn.lock * Address feedback
Summary
Depends on #35749(merged).Addresses #40160
This PR isn't easy. This prepares for i18n by adding strong types to Canvas Functions. I'm publishing this as a WIP to gather feedback as I go.
It's taken me several days to get Typescript working with Canvas Functions. But, as a result of that effort, we have a ton of new features to support i18n:
Define and Enforce Function Arguments
Canvas Functions have their arguments defined as individual properties of the
argsproperty. Each argument has one or more types, regardless of if it's expecting an array or single value of that type, expressed as an array of strings:This difference is now typed, and the type of each argument is available to
fn:In addition, the presence of the
resolveproperty set tofalsewill now enforce that the argument types be functions:Define and Enforce Context
By providing a generic type to represent the context passed into the Function, we can enforce it in
fn: