-
Notifications
You must be signed in to change notification settings - Fork 24
Description
Bug Description
When using TypeScript with exactOptionalPropertyTypes: true (a strict compiler option), the @azure/functions package fails to compile due to a type incompatibility in src/utils/toolProperties.ts.
Error Message
node_modules/@azure/functions/src/utils/toolProperties.ts:226:5 - error TS2322: Type '{ propertyName: string; propertyType: string; description: string; isRequired: boolean | undefined; isArray: boolean | undefined; }[]' is not assignable to type 'McpToolProperty[]'.
Type '{ propertyName: string; propertyType: string; description: string; isRequired: boolean | undefined; isArray: boolean | undefined; }' is not assignable to type 'McpToolProperty' with 'exactOptionalPropertyTypes: true'. Consider adding 'undefined' to the types of the target's properties.
Types of property 'isRequired' are incompatible.
Type 'boolean | undefined' is not assignable to type 'boolean'.
Type 'undefined' is not assignable to type 'boolean'.
226 return Object.entries(args).map(([propertyName, property]) => ({
~~~~~~
Environment
- @azure/functions version: 4.7.2 (also tested with 4.9.0)
- TypeScript version: 5.9.3
- Compiler option:
exactOptionalPropertyTypes: true
Root Cause
In src/utils/toolProperties.ts at line 226-232, the convertToolProperties function creates objects with properties that may be undefined:
return Object.entries(args).map(([propertyName, property]) => ({
propertyName,
propertyType: property.propertyType,
description: property.description || '',
isRequired: property.isRequired, // Type: boolean | undefined
isArray: property.isArray, // Type: boolean | undefined
}));However, the target interface McpToolProperty (in types/mcpTool.d.ts) defines these as optional properties:
export interface McpToolProperty {
propertyName: string;
propertyType: string;
description?: string;
isRequired?: boolean;
isArray?: boolean;
}With exactOptionalPropertyTypes: true, TypeScript distinguishes between:
isRequired?: boolean→ property can be omitted, but when present must bebooleanisRequired: boolean | undefined→ property must be present, but can beboolean | undefined
Assigning a value that might be undefined to an optional property is not allowed under this strict mode.
Suggested Fix
The fix is to only include the properties when they have defined values. Here's the corrected code:
export function convertToolProperties(args: Args): McpToolProperty[] {
return Object.entries(args).map(([propertyName, property]) => {
const result: McpToolProperty = {
propertyName,
propertyType: property.propertyType,
description: property.description || '',
};
if (property.isRequired !== undefined) {
result.isRequired = property.isRequired;
}
if (property.isArray !== undefined) {
result.isArray = property.isArray;
}
return result;
});
}Alternatively, use the nullish coalescing operator to provide defaults:
return Object.entries(args).map(([propertyName, property]) => ({
propertyName,
propertyType: property.propertyType,
description: property.description || '',
isRequired: property.isRequired ?? true, // Default to true
isArray: property.isArray ?? false, // Default to false
}));Workaround
For users encountering this issue, you can add skipLibCheck: true to your tsconfig.json compilerOptions to bypass type checking of library files.
Additional Context
The exactOptionalPropertyTypes option is part of TypeScript's strict mode family and helps catch subtle bugs related to optional properties. While it's a strict option, library code should ideally be compatible with all strict mode settings.