@@ -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 ;
@@ -1015,13 +1014,13 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
10151014 * @example
10161015 * var x = node.getAttr('x');
10171016 */
1018- getAttr < T > ( attr : string ) {
1019- const method = 'get' + Util . _capitalize ( attr ) ;
1017+ getAttr < AttrConfig extends Config , K extends AnyString < keyof Config > > ( attr : K ) : K extends keyof AttrConfig ? AttrConfig [ K ] : any {
1018+ const method = 'get' + Util . _capitalize ( attr as string ) ;
10201019 if ( Util . _isFunction ( ( this as any ) [ method ] ) ) {
10211020 return ( this as any ) [ method ] ( ) ;
10221021 }
10231022 // otherwise get directly
1024- return this . attrs [ attr ] as T | undefined ;
1023+ return this . attrs [ attr ] ;
10251024 }
10261025 /**
10271026 * get ancestors
@@ -1050,8 +1049,8 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
10501049 * @name Konva.Node#getAttrs
10511050 * @returns {Object }
10521051 */
1053- getAttrs ( ) {
1054- return ( this . attrs || { } ) as Config & Record < string , any > ;
1052+ getAttrs ( ) : Config {
1053+ return ( this . attrs || { } ) ;
10551054 }
10561055 /**
10571056 * set multiple attrs at once using an object literal
@@ -1065,7 +1064,7 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
10651064 * fill: 'red'
10661065 * });
10671066 */
1068- setAttrs ( config : any ) {
1067+ setAttrs ( config ?: Config ) {
10691068 this . _batchTransformChanges ( ( ) => {
10701069 let key , method ;
10711070 if ( ! config ) {
@@ -1624,7 +1623,7 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
16241623 * @returns {Object }
16251624 */
16261625 toObject ( ) {
1627- let attrs = this . getAttrs ( ) as any ,
1626+ let attrs = this . getAttrs ( ) ,
16281627 key ,
16291628 val ,
16301629 getter ,
@@ -2405,8 +2404,8 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
24052404 * @example
24062405 * node.setAttr('x', 5);
24072406 */
2408- setAttr ( attr : string , val ) {
2409- const func = this [ SET + Util . _capitalize ( attr ) ] ;
2407+ setAttr < AttrConfig extends Config , K extends AnyString < keyof Config > > ( attr : K , val : K extends keyof AttrConfig ? AttrConfig [ K ] : any ) {
2408+ const func = this [ SET + Util . _capitalize ( attr as string ) ] ;
24102409
24112410 if ( Util . _isFunction ( func ) ) {
24122411 func . call ( this , val ) ;
@@ -2422,7 +2421,7 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
24222421 drawNode ?. batchDraw ( ) ;
24232422 }
24242423 }
2425- _setAttr ( key : string , val ) {
2424+ _setAttr < AttrConfig extends Config , K extends AnyString < keyof Config > > ( key : K , val : K extends keyof AttrConfig ? AttrConfig [ K ] : any ) {
24262425 const oldVal = this . attrs [ key ] ;
24272426 if ( oldVal === val && ! Util . isObject ( val ) ) {
24282427 return ;
@@ -2878,7 +2877,7 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
28782877 }
28792878}
28802879
2881- interface AnimTo extends NodeConfig {
2880+ interface AnimTo extends NodeConfig < Record < string , any > > {
28822881 onFinish ?: Function ;
28832882 onUpdate ?: Function ;
28842883 duration ?: number ;
0 commit comments