Skip to content
3 changes: 3 additions & 0 deletions .changelog/5978-fix-shipped-typings.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
### Fixed

- Fixed type errors in the published typings when `skipLibCheck` is turned off, in PR [#5978](https://github.com/microsoft/BotFramework-WebChat/pull/5978), by [@OEvgeny](https://github.com/OEvgeny)
11 changes: 8 additions & 3 deletions packages/api/src/decorator/private/templateDecorator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,11 @@ export default function templateDecorator<
};
}

export type InferMiddleware<T extends ReturnType<typeof templateDecorator>> = T['~types']['middleware'];
export type InferProps<T extends ReturnType<typeof templateDecorator>> = T['~types']['props'];
export type InferRequest<T extends ReturnType<typeof templateDecorator>> = T['~types']['request'];
// Only constrain on `~types`: under `strictFunctionTypes`, a template with specific props is not assignable to `ReturnType<typeof templateDecorator>`.
type TemplateDecoratorTypes = {
readonly '~types': { readonly middleware: unknown; readonly props: unknown; readonly request: unknown };
};

export type InferMiddleware<T extends TemplateDecoratorTypes> = T['~types']['middleware'];
export type InferProps<T extends TemplateDecoratorTypes> = T['~types']['props'];
export type InferRequest<T extends TemplateDecoratorTypes> = T['~types']['request'];
11 changes: 8 additions & 3 deletions packages/api/src/types/WebSpeechPonyfill.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
/* globals SpeechGrammarList, SpeechRecognition, SpeechSynthesis */
/* globals SpeechSynthesis */

import { type TypeOfGlobal } from '@msinternal/botframework-webchat-base/utils';

// `SpeechGrammarList` and `SpeechRecognition` are not in TypeScript's DOM library, they come from `@types/dom-speech-recognition`.
// Use `typeof SpeechGrammarList`/`typeof SpeechRecognition` again when TypeScript's DOM library includes them.

type WebSpeechPonyfill = {
/**
Expand All @@ -9,10 +14,10 @@ type WebSpeechPonyfill = {
resumeAudioContext?: () => Promise<void>;

/** Polyfill for Web Speech API `SpeechGrammarList` class. */
SpeechGrammarList?: typeof SpeechGrammarList;
SpeechGrammarList?: TypeOfGlobal<'SpeechGrammarList', new () => object>;

/** Polyfill for Web Speech API `SpeechRecognition` class. */
SpeechRecognition?: typeof SpeechRecognition;
SpeechRecognition?: TypeOfGlobal<'SpeechRecognition', new () => object>;

/** Polyfill for Web Speech API `speechSynthesis` instance. */
speechSynthesis?: SpeechSynthesis;
Expand Down
10 changes: 10 additions & 0 deletions packages/base/src/utils/TypeOfGlobal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* Type of a global, or `Fallback` if the consumer's global types do not declare it.
*
* Use this instead of `typeof X` in published typings when `X` is not in TypeScript's DOM library, e.g. `setImmediate`
* (Node.js types) or `SpeechRecognition` (`@types/dom-speech-recognition`), so consumers without these types do not get
* "Cannot find name".
*/
type TypeOfGlobal<Name extends string, Fallback> = typeof globalThis extends Record<Name, infer T> ? T : Fallback;

export { type TypeOfGlobal };
1 change: 1 addition & 0 deletions packages/base/src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ export { default as iterateEquals } from './iterateEquals';
export { type OneOrMany } from './OneOrMany';
export { default as singleToArray } from './singleToArray';
export { default as toSpliced } from './toSpliced';
export { type TypeOfGlobal } from './TypeOfGlobal';
export { default as warnOnce } from './warnOnce';
export { default as withResolvers, type PromiseWithResolvers } from './withResolvers';
5 changes: 1 addition & 4 deletions packages/bundle/src/boot/actual/component/minimal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,5 @@ export {
UploadButton,
VideoContent,
VimeoContent,
YouTubeContent,
type BasicWebChatProps,
type ComposerProps,
type ReactWebChatProps
YouTubeContent
} from 'botframework-webchat-component/component.js';
5 changes: 1 addition & 4 deletions packages/bundle/src/boot/actual/decorator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@ export {
createActivityBorderMiddleware,
createActivityGroupingMiddleware,
DecoratorComposer,
useDecoratorRequest,
type ActivityBorderDecoratorProps,
type DecoratorMiddleware,
type InferDecoratorRequest
useDecoratorRequest
} from 'botframework-webchat-api/decorator.js';
export { BorderFlair, BorderLoader, WebChatDecorator } from 'botframework-webchat-component/decorator.js';
4 changes: 1 addition & 3 deletions packages/bundle/src/boot/actual/hook/minimal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,5 @@ export {
useVoiceRecordingMuted,
useVoiceSelector,
useVoiceState,
useWebSpeechPonyfill,
type DropZoneState,
type SendBoxFocusOptions
useWebSpeechPonyfill
} from 'botframework-webchat-component/hook.js';
12 changes: 2 additions & 10 deletions packages/bundle/src/boot/actual/internal.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
// We should review exports in this file to make sure 1P = 3P.
export {
type ActivityMiddleware,
type ActivityStatusMiddleware,
type TypingIndicatorMiddleware
} from 'botframework-webchat-api';
export { usePostVoiceActivity, useShouldShowMicrophoneButton } from 'botframework-webchat-api/internal.js';
export {
CodeHighlighterComposer,
Expand All @@ -16,14 +11,11 @@ export {
serializeDocumentFragmentIntoString,
useActivityStyleOptions,
useCodeHighlighter,
useLiveRegion,
type HighlightCodeFn
useLiveRegion
} from 'botframework-webchat-component/internal.js';
export {
getOrgSchemaMessage,
getVoiceActivityRole,
getVoiceActivityText,
isVoiceTranscriptActivity,
type DirectLineCardAction,
type WebChatActivity
isVoiceTranscriptActivity
} from 'botframework-webchat-core';
3 changes: 2 additions & 1 deletion packages/bundle/src/boot/actual/minimal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ const { object: buildInfoObject, version } = buildInfo;
// #endregion

export { concatMiddleware, createStyleSet, testIds, withEmoji } from 'botframework-webchat-component';
export { type ReactWebChatProps } from 'botframework-webchat-component/component.js';
export { Constants, createStore, createStoreWithDevTools, createStoreWithOptions } from 'botframework-webchat-core';
export { default as createBrowserWebSpeechPonyfillFactory } from '../../createBrowserWebSpeechPonyfillFactory';
export { ReactWebChat, type ReactWebChatProps } from './component/minimal';
export { ReactWebChat } from './component/minimal';
export { default as createDirectLine } from './private/createDirectLine';
export { default as createDirectLineAppServiceExtension } from './private/createDirectLineAppServiceExtension';
export { renderWebChat } from './renderWebChat/minimal';
Expand Down
7 changes: 7 additions & 0 deletions packages/bundle/src/boot/exports/component.ts
Original file line number Diff line number Diff line change
@@ -1 +1,8 @@
export * from '../actual/component/full';

// Types are exported here instead of `../actual/component/minimal`, see the namespaces in `./minimal.ts`.
export {
type BasicWebChatProps,
type ComposerProps,
type ReactWebChatProps
} from 'botframework-webchat-component/component.js';
7 changes: 7 additions & 0 deletions packages/bundle/src/boot/exports/decorator.ts
Original file line number Diff line number Diff line change
@@ -1 +1,8 @@
export * from '../actual/decorator';

// Types are exported here instead of `../actual/decorator`, see the namespaces in `./minimal.ts`.
export {
type ActivityBorderDecoratorProps,
type DecoratorMiddleware,
type InferDecoratorRequest
} from 'botframework-webchat-api/decorator.js';
3 changes: 3 additions & 0 deletions packages/bundle/src/boot/exports/hook.ts
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
export * from '../actual/hook/full';

// Types are exported here instead of `../actual/hook/minimal`, see the namespaces in `./minimal.ts`.
export { type DropZoneState, type SendBoxFocusOptions } from 'botframework-webchat-component/hook.js';
9 changes: 9 additions & 0 deletions packages/bundle/src/boot/exports/internal.ts
Original file line number Diff line number Diff line change
@@ -1 +1,10 @@
export * from '../actual/internal';

// Types are exported here instead of `../actual/internal`, see the namespaces in `./minimal.ts`.
export {
type ActivityMiddleware,
type ActivityStatusMiddleware,
type TypingIndicatorMiddleware
} from 'botframework-webchat-api';
export { type HighlightCodeFn } from 'botframework-webchat-component/internal.js';
export { type DirectLineCardAction, type WebChatActivity } from 'botframework-webchat-core';
2 changes: 2 additions & 0 deletions packages/bundle/src/boot/exports/minimal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ export { ReactWebChat as default } from '../actual/minimal'; // export * does no

// #region Backward compatibility
// Web devs should move to named exports instead.
// Keep types out of these namespaces until rollup-plugin-dts (used by tsup) emits types imported from another package as types:
// it emits them as `declare const X: typeof X`, which fails type checking (TS2693). Entry points export them instead, e.g. `./decorator.ts`.
export * as Components from '../actual/component/minimal';
export * as decorator from '../actual/decorator';
export * as hooks from '../actual/hook/minimal';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
/** @jest-environment @happy-dom/jest-environment */
/// <reference types="jest" />

import createStreamingRenderer, { STREAMING_ERROR } from './createStreamingRenderer';
import createMarkdownStreamingRenderer, { STREAMING_ERROR } from './createMarkdownStreamingRenderer';

const OPTIONS: Parameters<typeof createStreamingRenderer>[0] = {
const OPTIONS: Parameters<typeof createMarkdownStreamingRenderer>[0] = {
markdownRespectCRLF: false
};

const INIT: Parameters<typeof createStreamingRenderer>[1] = {
const INIT: Parameters<typeof createMarkdownStreamingRenderer>[1] = {
externalLinkAlt: 'Opens in a new window'
};

Expand All @@ -18,7 +18,7 @@ function setup() {

document.body.appendChild(container);

const renderer = createStreamingRenderer(OPTIONS, INIT);
const renderer = createMarkdownStreamingRenderer(OPTIONS, INIT);

currentContainer = container;

Expand Down Expand Up @@ -80,7 +80,7 @@ function splitBySentinel(container: HTMLElement): [string, string] | null {
return [committedDiv.innerHTML.trim(), activeDiv.innerHTML.trim()];
}

describe('createStreamingRenderer', () => {
describe('createMarkdownStreamingRenderer', () => {
afterEach(() => {
if (!currentContainer) {
return;
Expand Down
Comment thread
compulim marked this conversation as resolved.
Resolved
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ function findTopLevelBlocks(events: ReadonlyArray<Event>): readonly BlockBoundar
return blocks;
}

export default function createStreamingRenderer(
export default function createMarkdownStreamingRenderer(
{ markdownRenderHTML, markdownRespectCRLF }: StreamingRenderOptions,
{ externalLinkAlt }: StreamingRenderInit
): StreamingRenderer {
Expand Down
7 changes: 4 additions & 3 deletions packages/bundle/src/markdown/renderMarkdown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ import katex from 'katex';
import { micromark } from 'micromark';
import { gfm, gfmHtml } from 'micromark-extension-gfm';

import createStreamingRenderer, {
import createMarkdownStreamingRenderer, {
type StreamingNextOptions,
type StreamingNextResult,
type StreamingRenderer,
type StreamingRenderOptions
} from './createStreamingRenderer';
} from './createMarkdownStreamingRenderer';
import { math, mathHtml } from './mathExtension';
import { createDecorate } from './private/createDecorate';
import iterateLinkDefinitions from './private/iterateLinkDefinitions';
Expand Down Expand Up @@ -67,6 +67,7 @@ export default function render(
return serializeDocumentFragmentIntoString(documentFragmentAfterMarkdown).trim();
}

render.createStreamingRenderer = createStreamingRenderer;
// The function is named differently than the property: in our typings, `typeof createStreamingRenderer` would refer to the property itself.
render.createStreamingRenderer = createMarkdownStreamingRenderer;

export { type StreamingNextOptions, type StreamingNextResult, type StreamingRenderer, type StreamingRenderOptions };
2 changes: 1 addition & 1 deletion packages/component/src/types/ContextOf.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { type Context } from 'react';

type ContextOf<T extends Context<unknown>> = T extends Context<infer C> ? C : never;
type ContextOf<T> = T extends Context<infer C> ? C : never;

export type { ContextOf };
10 changes: 6 additions & 4 deletions packages/core/src/types/internal/GlobalScopeClock.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { type TypeOfGlobal } from '@msinternal/botframework-webchat-base/utils';

export type GlobalScopeClock = {
// eslint-disable-next-line no-restricted-globals
cancelAnimationFrame?: typeof cancelAnimationFrame | undefined;
// eslint-disable-next-line no-restricted-globals
cancelIdleCallback?: typeof cancelIdleCallback | undefined;
// eslint-disable-next-line no-restricted-globals
clearImmediate?: typeof clearImmediate | undefined;
// `setImmediate` and `clearImmediate` are Node.js globals, not in TypeScript's DOM library.
// Fallbacks are the same types as in `env.d.ts`.
clearImmediate?: TypeOfGlobal<'clearImmediate', (timeout: number) => void> | undefined;
// eslint-disable-next-line no-restricted-globals
clearInterval?: typeof clearInterval | undefined;
// eslint-disable-next-line no-restricted-globals
Expand All @@ -15,8 +18,7 @@ export type GlobalScopeClock = {
requestAnimationFrame?: typeof requestAnimationFrame | undefined;
// eslint-disable-next-line no-restricted-globals
requestIdleCallback?: typeof requestIdleCallback | undefined;
// eslint-disable-next-line no-restricted-globals
setImmediate?: typeof setImmediate | undefined;
setImmediate?: TypeOfGlobal<'setImmediate', (fn: () => void) => number> | undefined;
// eslint-disable-next-line no-restricted-globals
setInterval?: typeof setInterval | undefined;
// eslint-disable-next-line no-restricted-globals
Expand Down
Loading