-
-
Notifications
You must be signed in to change notification settings - Fork 924
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
feat: Factory types #1812
base: master
Are you sure you want to change the base?
feat: Factory types #1812
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,75 @@ | ||
import { Node } from './Node'; | ||
import { GetSet } from './types'; | ||
import { Util } from './Util'; | ||
import { getComponentValidator } from './Validators'; | ||
|
||
var GET = 'get', | ||
SET = 'set'; | ||
const GET = 'get'; | ||
const SET = 'set'; | ||
|
||
/** | ||
* Enforces that a type is a string. | ||
*/ | ||
type EnforceString<T> = T extends string ? T : never; | ||
|
||
/** | ||
* Represents a class. | ||
*/ | ||
type Constructor = abstract new (...args: any) => any; | ||
|
||
/** | ||
* An attribute of an instance of the provided class. Attributes names be strings. | ||
*/ | ||
type Attr<T extends Constructor> = EnforceString<keyof InstanceType<T>>; | ||
|
||
/** | ||
* A function that is called after a setter is called. | ||
*/ | ||
type AfterFunc<T extends Constructor> = (this: InstanceType<T>) => void; | ||
|
||
/** | ||
* Extracts the type of a GetSet. | ||
*/ | ||
type ExtractGetSet<T> = T extends GetSet<infer U, any> ? U : never; | ||
|
||
/** | ||
* Extracts the type of a GetSet class attribute. | ||
*/ | ||
type Value<T extends Constructor, U extends Attr<T>> = ExtractGetSet< | ||
InstanceType<T>[U] | ||
>; | ||
|
||
/** | ||
* A function that validates a value. | ||
*/ | ||
type ValidatorFunc<T> = (val: ExtractGetSet<T>, attr: string) => T; | ||
|
||
/** | ||
* Extracts the "components" (keys) of a GetSet value. The value must be an object. | ||
*/ | ||
type ExtractComponents<T extends Constructor, U extends Attr<T>> = Value< | ||
T, | ||
U | ||
> extends Record<string, any> | ||
? EnforceString<keyof Value<T, U>>[] | ||
: never; | ||
|
||
export const Factory = { | ||
addGetterSetter(constructor, attr, def?, validator?, after?) { | ||
addGetterSetter<T extends Constructor, U extends Attr<T>>( | ||
constructor: T, | ||
attr: U, | ||
def?: Value<T, U>, | ||
validator?: ValidatorFunc<Value<T, U>>, | ||
after?: AfterFunc<T> | ||
): void { | ||
Factory.addGetter(constructor, attr, def); | ||
Factory.addSetter(constructor, attr, validator, after); | ||
Factory.addOverloadedGetterSetter(constructor, attr); | ||
}, | ||
addGetter(constructor, attr, def?) { | ||
addGetter<T extends Constructor, U extends Attr<T>>( | ||
constructor: T, | ||
attr: U, | ||
def?: Value<T, U> | ||
) { | ||
var method = GET + Util._capitalize(attr); | ||
|
||
constructor.prototype[method] = | ||
|
@@ -22,14 +80,25 @@ export const Factory = { | |
}; | ||
}, | ||
|
||
addSetter(constructor, attr, validator?, after?) { | ||
addSetter<T extends Constructor, U extends Attr<T>>( | ||
constructor: T, | ||
attr: U, | ||
validator?: ValidatorFunc<Value<T, U>>, | ||
after?: AfterFunc<T> | ||
) { | ||
var method = SET + Util._capitalize(attr); | ||
|
||
if (!constructor.prototype[method]) { | ||
Factory.overWriteSetter(constructor, attr, validator, after); | ||
} | ||
}, | ||
overWriteSetter(constructor, attr, validator?, after?) { | ||
|
||
overWriteSetter<T extends Constructor, U extends Attr<T>>( | ||
constructor: T, | ||
attr: U, | ||
validator?: ValidatorFunc<Value<T, U>>, | ||
after?: AfterFunc<T> | ||
) { | ||
var method = SET + Util._capitalize(attr); | ||
constructor.prototype[method] = function (val) { | ||
if (validator && val !== undefined && val !== null) { | ||
|
@@ -45,12 +114,13 @@ export const Factory = { | |
return this; | ||
}; | ||
}, | ||
addComponentsGetterSetter( | ||
constructor, | ||
attr: string, | ||
components: Array<string>, | ||
validator?: Function, | ||
after?: Function | ||
|
||
addComponentsGetterSetter<T extends Constructor, U extends Attr<T>>( | ||
constructor: T, | ||
attr: U, | ||
components: ExtractComponents<T, U>, | ||
validator?: ValidatorFunc<Value<T, U>>, | ||
after?: AfterFunc<T> | ||
) { | ||
var len = components.length, | ||
capitalize = Util._capitalize, | ||
|
@@ -79,7 +149,7 @@ export const Factory = { | |
key; | ||
|
||
if (validator) { | ||
val = validator.call(this, val); | ||
val = validator.call(this, val, attr); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What does this change do? |
||
} | ||
|
||
if (basicValidator) { | ||
|
@@ -109,7 +179,10 @@ export const Factory = { | |
|
||
Factory.addOverloadedGetterSetter(constructor, attr); | ||
}, | ||
addOverloadedGetterSetter(constructor, attr) { | ||
addOverloadedGetterSetter<T extends Constructor, U extends Attr<T>>( | ||
constructor: T, | ||
attr: U | ||
) { | ||
var capitalizedAttr = Util._capitalize(attr), | ||
setter = SET + capitalizedAttr, | ||
getter = GET + capitalizedAttr; | ||
|
@@ -124,7 +197,12 @@ export const Factory = { | |
return this[getter](); | ||
}; | ||
}, | ||
addDeprecatedGetterSetter(constructor, attr, def, validator) { | ||
addDeprecatedGetterSetter<T extends Constructor, U extends Attr<T>>( | ||
constructor: T, | ||
attr: U, | ||
def: Value<T, U>, | ||
validator: ValidatorFunc<Value<T, U>> | ||
) { | ||
Util.error('Adding deprecated ' + attr); | ||
|
||
var method = GET + Util._capitalize(attr); | ||
|
@@ -142,7 +220,10 @@ export const Factory = { | |
}); | ||
Factory.addOverloadedGetterSetter(constructor, attr); | ||
}, | ||
backCompat(constructor, methods) { | ||
backCompat<T extends Constructor>( | ||
constructor: T, | ||
methods: Record<string, string> | ||
) { | ||
Util.each(methods, function (oldMethodName, newMethodName) { | ||
var method = constructor.prototype[newMethodName]; | ||
var oldGetter = GET + Util._capitalize(oldMethodName); | ||
|
@@ -164,7 +245,7 @@ export const Factory = { | |
constructor.prototype[oldSetter] = deprecated; | ||
}); | ||
}, | ||
afterSetFilter(this: Node) { | ||
afterSetFilter(this: Node): void { | ||
this._filterUpToDate = false; | ||
}, | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2660,7 +2660,7 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> { | |
rotation: GetSet<number, this>; | ||
zIndex: GetSet<number, this>; | ||
|
||
scale: GetSet<Vector2d | undefined, this>; | ||
scale: GetSet<Vector2d, this>; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Either this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like it is not correct, I don't think |
||
scaleX: GetSet<number, this>; | ||
scaleY: GetSet<number, this>; | ||
skew: GetSet<Vector2d, this>; | ||
|
@@ -3102,7 +3102,7 @@ addGetterSetter(Node, 'offsetY', 0, getNumberValidator()); | |
* node.offsetY(3); | ||
*/ | ||
|
||
addGetterSetter(Node, 'dragDistance', null, getNumberValidator()); | ||
addGetterSetter(Node, 'dragDistance', undefined, getNumberValidator()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a subtle API change. Perhaps we should widen the type of There are a number of other places where the initial value is set to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The drag distance must be always number. So |
||
|
||
/** | ||
* get/set drag distance | ||
|
@@ -3193,7 +3193,7 @@ addGetterSetter(Node, 'listening', true, getBooleanValidator()); | |
|
||
addGetterSetter(Node, 'preventDefault', true, getBooleanValidator()); | ||
|
||
addGetterSetter(Node, 'filters', null, function (this: Node, val) { | ||
addGetterSetter(Node, 'filters', undefined, function (this: Node, val) { | ||
this._filterUpToDate = false; | ||
return val; | ||
}); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -843,6 +843,11 @@ export class Shape< | |
strokeLinearGradientStartPoint: GetSet<Vector2d, this>; | ||
strokeLinearGradientEndPoint: GetSet<Vector2d, this>; | ||
strokeLinearGradientColorStops: GetSet<Array<number | string>, this>; | ||
strokeLinearGradientStartPointX: GetSet<number, this>; | ||
strokeLinearGradientStartPointY: GetSet<number, this>; | ||
strokeLinearGradientEndPointX: GetSet<number, this>; | ||
strokeLinearGradientEndPointY: GetSet<number, this>; | ||
fillRule: GetSet<CanvasFillRule, this>; | ||
Comment on lines
+846
to
+850
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These annotations were missing. I don't think this changes anything because the Factory adds the |
||
} | ||
|
||
Shape.prototype._fillFunc = _fillFunc; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think I have understood the intention with these validators - they should create warnings but otherwise let the value through, even if it is invalid. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -317,7 +317,10 @@ export class Tag extends Shape<TagConfig> { | |
}; | ||
} | ||
|
||
pointerDirection: GetSet<'left' | 'top' | 'right' | 'bottom', this>; | ||
pointerDirection: GetSet< | ||
'left' | 'top' | 'right' | 'bottom' | typeof NONE, | ||
this | ||
>; | ||
Comment on lines
+320
to
+323
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The factory sets the initial value to |
||
pointerWidth: GetSet<number, this>; | ||
pointerHeight: GetSet<number, this>; | ||
cornerRadius: GetSet<number, this>; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -551,7 +551,7 @@ Factory.addGetterSetter(TextPath, 'text', EMPTY_STRING); | |
* // underline text | ||
* shape.textDecoration('underline'); | ||
*/ | ||
Factory.addGetterSetter(TextPath, 'textDecoration', null); | ||
Factory.addGetterSetter(TextPath, 'textDecoration', undefined); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This probably should be an empty string as in Text class. |
||
|
||
/** | ||
* get/set kerning function. | ||
|
@@ -568,4 +568,4 @@ Factory.addGetterSetter(TextPath, 'textDecoration', null); | |
* return 1; | ||
* }); | ||
*/ | ||
Factory.addGetterSetter(TextPath, 'kerningFunc', null); | ||
Factory.addGetterSetter(TextPath, 'kerningFunc', undefined); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1745,8 +1745,6 @@ Factory.addGetterSetter(Transformer, 'ignoreStroke', false); | |
*/ | ||
Factory.addGetterSetter(Transformer, 'padding', 0, getNumberValidator()); | ||
|
||
Factory.addGetterSetter(Transformer, 'node'); | ||
|
||
Comment on lines
-1748
to
-1749
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this was added accidentally - There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is an old (deprecated) API. Should be safe to remove. |
||
/** | ||
* get/set attached nodes of the Transformer. Transformer will adapt to their size and listen to their events | ||
* @method | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can make this a bit safer with a type to constrain
attr
to be aGetSet
.Then, type
attr
asattr: EnforceGetSet<T, U>
.However, this causes a problem in
Canvas.ts
at https://github.com/psychedelicious/konva/blob/9c41a6eed1bba46e80ce282903ac86bb11493e84/src/Canvas.ts#L171