Skip to content

Commit a62399e

Browse files
authored
Add types for 'as' binding (#139)
1 parent ec8381a commit a62399e

File tree

3 files changed

+69
-3
lines changed

3 files changed

+69
-3
lines changed

.changeset/rotten-readers-cheat.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@knuckles/typescript": minor
3+
---
4+
5+
Add types for 'as' binding.

packages/typescript/src/transpiler/transpiler.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ export class Transpiler {
6767

6868
type BindingDeclarationMetadata = {
6969
requiresContextParamater: boolean;
70+
requiresBindingsParamater: boolean;
7071
returnsChildContext: boolean;
7172
};
7273

@@ -147,6 +148,13 @@ class Renderer {
147148
);
148149
assertOrBroken(requiresContextParamaterTrait);
149150

151+
const requiresBindingsParamaterTrait = getDescendantOfKind(
152+
traitsNs,
153+
ts.SyntaxKind.TypeAliasDeclaration,
154+
"RequiresBindingsParamater",
155+
);
156+
assertOrBroken(requiresBindingsParamaterTrait);
157+
150158
const strictnessNs = getDescendantOfKind(
151159
knucklesNs,
152160
ts.SyntaxKind.ModuleDeclaration,
@@ -171,6 +179,9 @@ class Renderer {
171179
const requiresContextParamater = requiresContextParamaterTrait
172180
.getType()
173181
.isAssignableTo(type);
182+
const requiresBindingsParamater = requiresBindingsParamaterTrait
183+
.getType()
184+
.isAssignableTo(type);
174185
const returnsChildContext = type.isAssignableTo(
175186
returnsChildContextTrait.getType(),
176187
);
@@ -179,6 +190,7 @@ class Renderer {
179190
name,
180191
{
181192
requiresContextParamater,
193+
requiresBindingsParamater,
182194
returnsChildContext,
183195
},
184196
];
@@ -453,6 +465,25 @@ class Renderer {
453465
chunk.append(", $context");
454466
}
455467

468+
if (meta?.requiresBindingsParamater) {
469+
chunk.append(", {").newline();
470+
471+
const siblings =
472+
binding.parent instanceof ko.Element
473+
? binding.parent.bindings
474+
: [binding];
475+
for (const sibling of siblings) {
476+
chunk
477+
.append(sibling.name.value)
478+
.append(": ")
479+
.append(sibling.param.value)
480+
.append(",")
481+
.newline();
482+
}
483+
484+
chunk.append("}");
485+
}
486+
456487
return chunk.append(")");
457488
}
458489

packages/typescript/types/index.d.ts

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ declare global {
1111
$rawData: any;
1212
}
1313

14+
export interface BindingMap {
15+
[key: string]: unknown;
16+
}
17+
1418
export type MaybeSubscribable<T> = T | ko.Subscribable<T>;
1519
export type MaybeSubscribableRecord<
1620
K extends string | number | symbol,
@@ -25,10 +29,17 @@ declare global {
2529
v: any,
2630
c: BindingContext,
2731
) => any;
32+
export type RequiresBindingsParamater = (
33+
n: Comment | Element,
34+
v: any,
35+
c: BindingContext,
36+
b: any,
37+
) => any;
2838
export type ReturnsChildContext = (
2939
n: Comment | Element,
3040
v: any,
3141
c: BindingContext,
42+
b?: any,
3243
) => BindingContext;
3344
}
3445

@@ -411,6 +422,8 @@ declare global {
411422
}
412423

413424
export interface Bindings {
425+
as: (n: Comment | Element, v: MaybeSubscribable<string>) => void;
426+
414427
/**
415428
* Adds event listeners for each entry in the provided record on the
416429
* element.
@@ -523,10 +536,12 @@ declare global {
523536
const K extends string,
524537
T extends MaybeSubscribable<unknown[] | readonly unknown[]>,
525538
C extends BindingContext,
539+
const B extends BindingMap,
526540
>(
527541
n: Comment | Element,
528542
v: { data: T; as: K } | T,
529543
c: C,
544+
b: B,
530545
) => {
531546
$parentContext: C | undefined;
532547
$parents: [C["$data"], ...C["$parents"]];
@@ -535,7 +550,13 @@ declare global {
535550
$data: Unwrapped<Unwrapped<T>[number]>;
536551
$rawData: Unwrapped<T>[number];
537552
$index: ko.Observable<number>;
538-
};
553+
} & {
554+
[_ in K]: Unwrapped<Unwrapped<T>[number]>;
555+
} & (B extends { as: any }
556+
? {
557+
[_ in Unwrapped<B["as"]>]: Unwrapped<Unwrapped<T>[number]>;
558+
}
559+
: {});
539560

540561
/**
541562
* @see https://knockoutjs.com/documentation/with-binding.html
@@ -544,18 +565,27 @@ declare global {
544565
/**
545566
* @see https://knockoutjs.com/documentation/with-binding.html
546567
*/
547-
with: <T extends object, C extends BindingContext>(
568+
with: <
569+
T extends object,
570+
C extends BindingContext,
571+
const B extends BindingMap,
572+
>(
548573
n: Comment | Element,
549574
v: T | ko.Observable<T>,
550575
c: C,
576+
b: B,
551577
) => {
552578
$parentContext: C;
553579
$parents: [C["$data"], ...C["$parents"]];
554580
$parent: C["$data"];
555581
$root: C["$root"];
556582
$data: Unwrapped<T>;
557583
$rawData: T;
558-
};
584+
} & (B extends { as: any }
585+
? {
586+
[_ in Unwrapped<B["as"]>]: Unwrapped<T>;
587+
}
588+
: {});
559589
/**
560590
* @see https://knockoutjs.com/documentation/let-binding.html
561591
*/

0 commit comments

Comments
 (0)