@@ -10,7 +10,7 @@ import type { Layer } from './Layer.ts';
1010import type { Shape } from './Shape.ts' ;
1111import type { Stage } from './Stage.ts' ;
1212import type { GetSet , IRect , Vector2d } from './types.ts' ;
13- import { Transform , Util } from './Util.ts' ;
13+ import { Transform , Util , type AnyString } from './Util.ts' ;
1414import {
1515 getBooleanValidator ,
1616 getNumberValidator ,
@@ -134,9 +134,8 @@ type globalCompositeOperationType =
134134 | 'color'
135135 | 'luminosity' ;
136136
137- export interface NodeConfig {
138- // allow any custom attribute
139- [ index : string ] : any ;
137+ // allow any custom attribute
138+ export type NodeConfig < Props extends Record < string , any > = { } > = Props & {
140139 x ?: number ;
141140 y ?: number ;
142141 width ?: number ;
@@ -223,6 +222,20 @@ export type KonvaEventListener<This, EventType> = (
223222 ev : KonvaEventObject < EventType , This >
224223) => void ;
225224
225+ export type CanvasConfig = {
226+ x ?: number ;
227+ y ?: number ;
228+ width ?: number ;
229+ height ?: number ;
230+ pixelRatio ?: number ;
231+ imageSmoothingEnabled ?: boolean ;
232+ } ;
233+
234+ export type ImageConfig = CanvasConfig & {
235+ mimeType ?: string ;
236+ quality ?: number ;
237+ } ;
238+
226239/**
227240 * Node constructor. Nodes are entities that can be transformed, layered,
228241 * and have bound events. The stage, layers, groups, and shapes all extend Node.
@@ -393,17 +406,13 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
393406 * drawBorder: true
394407 * });
395408 */
396- cache ( config ?: {
397- x ?: number ;
398- y ?: number ;
399- width ?: number ;
400- height ?: number ;
401- drawBorder ?: boolean ;
402- offset ?: number ;
403- pixelRatio ?: number ;
404- imageSmoothingEnabled ?: boolean ;
405- hitCanvasPixelRatio ?: number ;
406- } ) {
409+ cache (
410+ config ?: CanvasConfig & {
411+ drawBorder ?: boolean ;
412+ offset ?: number ;
413+ hitCanvasPixelRatio ?: number ;
414+ }
415+ ) {
407416 const conf = config || { } ;
408417 let rect = { } as IRect ;
409418
@@ -1015,13 +1024,13 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
10151024 * @example
10161025 * var x = node.getAttr('x');
10171026 */
1018- getAttr < T > ( attr : string ) {
1019- const method = 'get' + Util . _capitalize ( attr ) ;
1027+ getAttr < AttrConfig extends Config , K extends AnyString < keyof Config > > ( attr : K ) : K extends keyof AttrConfig ? AttrConfig [ K ] : any {
1028+ const method = 'get' + Util . _capitalize ( attr as string ) ;
10201029 if ( Util . _isFunction ( ( this as any ) [ method ] ) ) {
10211030 return ( this as any ) [ method ] ( ) ;
10221031 }
10231032 // otherwise get directly
1024- return this . attrs [ attr ] as T | undefined ;
1033+ return this . attrs [ attr ] ;
10251034 }
10261035 /**
10271036 * get ancestors
@@ -1050,8 +1059,8 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
10501059 * @name Konva.Node#getAttrs
10511060 * @returns {Object }
10521061 */
1053- getAttrs ( ) {
1054- return ( this . attrs || { } ) as Config & Record < string , any > ;
1062+ getAttrs ( ) : Config {
1063+ return ( this . attrs || { } ) ;
10551064 }
10561065 /**
10571066 * set multiple attrs at once using an object literal
@@ -1065,7 +1074,7 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
10651074 * fill: 'red'
10661075 * });
10671076 */
1068- setAttrs ( config : any ) {
1077+ setAttrs ( config ?: Config ) {
10691078 this . _batchTransformChanges ( ( ) => {
10701079 let key , method ;
10711080 if ( ! config ) {
@@ -1624,7 +1633,7 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
16241633 * @returns {Object }
16251634 */
16261635 toObject ( ) {
1627- let attrs = this . getAttrs ( ) as any ,
1636+ let attrs = this . getAttrs ( ) ,
16281637 key ,
16291638 val ,
16301639 getter ,
@@ -2111,7 +2120,7 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
21112120 * @example
21122121 * var canvas = node.toCanvas();
21132122 */
2114- toCanvas ( config ?) {
2123+ toCanvas ( config ?: CanvasConfig ) {
21152124 return this . _toKonvaCanvas ( config ) . _canvas ;
21162125 }
21172126 /**
@@ -2137,16 +2146,11 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
21372146 * @param {Boolean } [config.imageSmoothingEnabled] set this to false if you want to disable imageSmoothing
21382147 * @returns {String }
21392148 */
2140- toDataURL ( config ?: {
2141- x ?: number ;
2142- y ?: number ;
2143- width ?: number ;
2144- height ?: number ;
2145- pixelRatio ?: number ;
2146- mimeType ?: string ;
2147- quality ?: number ;
2148- callback ?: ( str : string ) => void ;
2149- } ) {
2149+ toDataURL (
2150+ config ?: ImageConfig & {
2151+ callback ?: ( url : string ) => void ;
2152+ }
2153+ ) {
21502154 config = config || { } ;
21512155 const mimeType = config . mimeType || null ,
21522156 quality = config . quality || null ;
@@ -2187,16 +2191,11 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
21872191 * }
21882192 * });
21892193 */
2190- toImage ( config ?: {
2191- x ?: number ;
2192- y ?: number ;
2193- width ?: number ;
2194- height ?: number ;
2195- pixelRatio ?: number ;
2196- mimeType ?: string ;
2197- quality ?: number ;
2198- callback ?: ( img : HTMLImageElement ) => void ;
2199- } ) {
2194+ toImage (
2195+ config ?: ImageConfig & {
2196+ callback ?: ( img : HTMLImageElement ) => void ;
2197+ }
2198+ ) {
22002199 return new Promise < HTMLImageElement > ( ( resolve , reject ) => {
22012200 try {
22022201 const callback = config ?. callback ;
@@ -2231,16 +2230,11 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
22312230 * var blob = await node.toBlob({});
22322231 * @returns {Promise<Blob> }
22332232 */
2234- toBlob ( config ?: {
2235- x ?: number ;
2236- y ?: number ;
2237- width ?: number ;
2238- height ?: number ;
2239- pixelRatio ?: number ;
2240- mimeType ?: string ;
2241- quality ?: number ;
2242- callback ?: ( blob : Blob | null ) => void ;
2243- } ) {
2233+ toBlob (
2234+ config ?: ImageConfig & {
2235+ callback ?: ( blob : Blob | null ) => void ;
2236+ }
2237+ ) {
22442238 return new Promise ( ( resolve , reject ) => {
22452239 try {
22462240 const callback = config ?. callback ;
@@ -2405,8 +2399,8 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
24052399 * @example
24062400 * node.setAttr('x', 5);
24072401 */
2408- setAttr ( attr : string , val ) {
2409- const func = this [ SET + Util . _capitalize ( attr ) ] ;
2402+ setAttr < AttrConfig extends Config , K extends AnyString < keyof Config > > ( attr : K , val : K extends keyof AttrConfig ? AttrConfig [ K ] : any ) {
2403+ const func = this [ SET + Util . _capitalize ( attr as string ) ] ;
24102404
24112405 if ( Util . _isFunction ( func ) ) {
24122406 func . call ( this , val ) ;
@@ -2422,7 +2416,7 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
24222416 drawNode ?. batchDraw ( ) ;
24232417 }
24242418 }
2425- _setAttr ( key : string , val ) {
2419+ _setAttr < AttrConfig extends Config , K extends AnyString < keyof Config > > ( key : K , val : K extends keyof AttrConfig ? AttrConfig [ K ] : any ) {
24262420 const oldVal = this . attrs [ key ] ;
24272421 if ( oldVal === val && ! Util . isObject ( val ) ) {
24282422 return ;
@@ -2878,7 +2872,7 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
28782872 }
28792873}
28802874
2881- interface AnimTo extends NodeConfig {
2875+ interface AnimTo extends NodeConfig < Record < string , any > > {
28822876 onFinish ?: Function ;
28832877 onUpdate ?: Function ;
28842878 duration ?: number ;
0 commit comments