feat: improve return types for render methods

- Change render methods from returning any to string
- Change internal generator methods from any to unknown
- Change evalValue methods from any to unknown
- Add suppressImplicitAnyIndexErrors to rollup config

This improves TypeScript support for users who depend on render method return types.

Fixes #832
This commit is contained in:
Yang Jun
2026-01-11 18:37:32 +08:00
parent b9d02811a9
commit d165f43492
3 changed files with 21 additions and 20 deletions
+2 -1
View File
@@ -23,7 +23,8 @@ const tsconfig = (target) => ({
compilerOptions: { compilerOptions: {
target, target,
module: 'ES2015', module: 'ES2015',
rootDir: 'src' rootDir: 'src',
suppressImplicitAnyIndexErrors: true
} }
} }
}) })
+18 -18
View File
@@ -30,30 +30,30 @@ export class Liquid {
return parser.parse(html, filepath) return parser.parse(html, filepath)
} }
public _render (tpl: Template[], scope: Context | object | undefined, renderOptions: RenderOptions): IterableIterator<any> { public _render (tpl: Template[], scope: Context | object | undefined, renderOptions: RenderOptions): IterableIterator<unknown> {
const ctx = scope instanceof Context ? scope : new Context(scope, this.options, renderOptions) const ctx = scope instanceof Context ? scope : new Context(scope, this.options, renderOptions)
return this.renderer.renderTemplates(tpl, ctx) return this.renderer.renderTemplates(tpl, ctx)
} }
public async render (tpl: Template[], scope?: object, renderOptions?: RenderOptions): Promise<any> { public async render (tpl: Template[], scope?: object, renderOptions?: RenderOptions): Promise<string> {
return toPromise(this._render(tpl, scope, { ...renderOptions, sync: false })) return toPromise(this._render(tpl, scope, { ...renderOptions, sync: false })) as Promise<string>
} }
public renderSync (tpl: Template[], scope?: object, renderOptions?: RenderOptions): any { public renderSync (tpl: Template[], scope?: object, renderOptions?: RenderOptions): string {
return toValueSync(this._render(tpl, scope, { ...renderOptions, sync: true })) return toValueSync(this._render(tpl, scope, { ...renderOptions, sync: true })) as string
} }
public renderToNodeStream (tpl: Template[], scope?: object, renderOptions: RenderOptions = {}): NodeJS.ReadableStream { public renderToNodeStream (tpl: Template[], scope?: object, renderOptions: RenderOptions = {}): NodeJS.ReadableStream {
const ctx = new Context(scope, this.options, renderOptions) const ctx = new Context(scope, this.options, renderOptions)
return this.renderer.renderTemplatesToNodeStream(tpl, ctx) return this.renderer.renderTemplatesToNodeStream(tpl, ctx)
} }
public _parseAndRender (html: string, scope: Context | object | undefined, renderOptions: RenderOptions): IterableIterator<any> { public _parseAndRender (html: string, scope: Context | object | undefined, renderOptions: RenderOptions): IterableIterator<unknown> {
const tpl = this.parse(html) const tpl = this.parse(html)
return this._render(tpl, scope, renderOptions) return this._render(tpl, scope, renderOptions)
} }
public async parseAndRender (html: string, scope?: Context | object, renderOptions?: RenderOptions): Promise<any> { public async parseAndRender (html: string, scope?: Context | object, renderOptions?: RenderOptions): Promise<string> {
return toPromise(this._parseAndRender(html, scope, { ...renderOptions, sync: false })) return toPromise(this._parseAndRender(html, scope, { ...renderOptions, sync: false })) as Promise<string>
} }
public parseAndRenderSync (html: string, scope?: Context | object, renderOptions?: RenderOptions): any { public parseAndRenderSync (html: string, scope?: Context | object, renderOptions?: RenderOptions): string {
return toValueSync(this._parseAndRender(html, scope, { ...renderOptions, sync: true })) return toValueSync(this._parseAndRender(html, scope, { ...renderOptions, sync: true })) as string
} }
public _parsePartialFile (file: string, sync?: boolean, currentFile?: string) { public _parsePartialFile (file: string, sync?: boolean, currentFile?: string) {
@@ -71,30 +71,30 @@ export class Liquid {
public parseFileSync (file: string, lookupType?: LookupType): Template[] { public parseFileSync (file: string, lookupType?: LookupType): Template[] {
return toValueSync<Template[]>(new Parser(this).parseFile(file, true, lookupType)) return toValueSync<Template[]>(new Parser(this).parseFile(file, true, lookupType))
} }
public * _renderFile (file: string, ctx: Context | object | undefined, renderFileOptions: RenderFileOptions): Generator<any> { public * _renderFile (file: string, ctx: Context | object | undefined, renderFileOptions: RenderFileOptions): Generator<unknown, unknown, unknown> {
const templates = (yield this._parseFile(file, renderFileOptions.sync, renderFileOptions.lookupType)) as Template[] const templates = (yield this._parseFile(file, renderFileOptions.sync, renderFileOptions.lookupType)) as Template[]
return yield this._render(templates, ctx, renderFileOptions) return yield this._render(templates, ctx, renderFileOptions)
} }
public async renderFile (file: string, ctx?: Context | object, renderFileOptions?: RenderFileOptions) { public async renderFile (file: string, ctx?: Context | object, renderFileOptions?: RenderFileOptions): Promise<string> {
return toPromise(this._renderFile(file, ctx, { ...renderFileOptions, sync: false })) return toPromise(this._renderFile(file, ctx, { ...renderFileOptions, sync: false })) as Promise<string>
} }
public renderFileSync (file: string, ctx?: Context | object, renderFileOptions?: RenderFileOptions) { public renderFileSync (file: string, ctx?: Context | object, renderFileOptions?: RenderFileOptions): string {
return toValueSync(this._renderFile(file, ctx, { ...renderFileOptions, sync: true })) return toValueSync(this._renderFile(file, ctx, { ...renderFileOptions, sync: true })) as string
} }
public async renderFileToNodeStream (file: string, scope?: object, renderOptions?: RenderOptions) { public async renderFileToNodeStream (file: string, scope?: object, renderOptions?: RenderOptions) {
const templates = await this.parseFile(file) const templates = await this.parseFile(file)
return this.renderToNodeStream(templates, scope, renderOptions) return this.renderToNodeStream(templates, scope, renderOptions)
} }
public _evalValue (str: string, scope?: object | Context): IterableIterator<any> { public _evalValue (str: string, scope?: object | Context): IterableIterator<unknown> {
const value = new Value(str, this) const value = new Value(str, this)
const ctx = scope instanceof Context ? scope : new Context(scope, this.options) const ctx = scope instanceof Context ? scope : new Context(scope, this.options)
return value.value(ctx) return value.value(ctx)
} }
public async evalValue (str: string, scope?: object | Context): Promise<any> { public async evalValue (str: string, scope?: object | Context): Promise<unknown> {
return toPromise(this._evalValue(str, scope)) return toPromise(this._evalValue(str, scope))
} }
public evalValueSync (str: string, scope?: object | Context): any { public evalValueSync (str: string, scope?: object | Context): unknown {
return toValueSync(this._evalValue(str, scope)) return toValueSync(this._evalValue(str, scope))
} }
+1 -1
View File
@@ -11,7 +11,7 @@ export class Render {
.then(() => emitter.end(), err => emitter.error(err)) .then(() => emitter.end(), err => emitter.error(err))
return emitter.stream return emitter.stream
} }
public * renderTemplates (templates: Template[], ctx: Context, emitter?: Emitter): IterableIterator<any> { public * renderTemplates (templates: Template[], ctx: Context, emitter?: Emitter): IterableIterator<unknown> {
if (!emitter) { if (!emitter) {
emitter = ctx.opts.keepOutputType ? new KeepingTypeEmitter() : new SimpleEmitter() emitter = ctx.opts.keepOutputType ? new KeepingTypeEmitter() : new SimpleEmitter()
} }