forked from strands-agents/sdk-typescript
-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Description
Overview
Add a base class for all content blocks to enable runtime type checking using instanceof checks. This will allow developers to easily determine if a value is any type of ContentBlock without needing to check against each individual block type.
Implementation Requirements
Technical Approach
Based on clarification discussion and repository analysis:
- Pattern: Abstract base class with type discriminator
- Naming: Use
ContentBlockBaseas the base class name, keepContentBlockas the union type - Backward Compatibility: MUST maintain - this is a non-breaking, additive change
- Files Affected:
src/types/messages.ts,src/types/media.ts, test files, exports
Base Class Design
Create an abstract base class that all content blocks will extend:
/**
* Base class for all content blocks.
* Enables runtime type checking using instanceof.
*
* @example
* ```typescript
* if (someValue instanceof ContentBlockBase) {
* // someValue is definitely a ContentBlock
* console.log(someValue.type)
* }
* ```
*/
export abstract class ContentBlockBase {
/**
* Discriminator for the content block type.
* Each subclass defines this as a specific string literal.
*/
abstract readonly type: string
}Content Block Classes to Update
In src/types/messages.ts (7 classes):
TextBlockToolUseBlockToolResultBlockReasoningBlockCachePointBlockGuardContentBlockJsonBlock
In src/types/media.ts (3 classes):
ImageBlockVideoBlockDocumentBlock
Each class MUST:
- Extend
ContentBlockBase - Keep existing
readonly type = '{name}Block' as const(TypeScript allows const string literals for abstract string properties) - Maintain all existing properties and methods
- Preserve existing constructor signatures
Example Implementation
// Before:
export class TextBlock implements TextBlockData {
readonly type = 'textBlock' as const
readonly text: string
constructor(data: string) { this.text = data }
}
// After:
export class TextBlock extends ContentBlockBase implements TextBlockData {
readonly type = 'textBlock' as const // Still works with abstract type: string
readonly text: string
constructor(data: string) {
super()
this.text = data
}
}Type Union (No Changes)
The existing ContentBlock type union MUST remain unchanged for backward compatibility:
export type ContentBlock =
| TextBlock
| ToolUseBlock
| ToolResultBlock
| ReasoningBlock
| CachePointBlock
| GuardContentBlock
| ImageBlock
| VideoBlock
| DocumentBlockExport Updates
In src/index.ts, add export for the base class:
// Message classes
export {
ContentBlockBase, // NEW
TextBlock,
ToolUseBlock,
// ... rest unchanged
} from './types/messages.js'Testing Requirements
In src/types/__tests__/messages.test.ts:
- Add test suite for
ContentBlockBase - Test instanceof checks for each block type
- Verify type property is accessible
- Test that non-block objects fail instanceof check
In src/types/__tests__/media.test.ts:
- Test instanceof checks for media blocks
- Verify media blocks are instanceof ContentBlockBase
Example test:
describe('ContentBlockBase', () => {
it('allows instanceof checks for TextBlock', () => {
const block = new TextBlock('test')
expect(block instanceof ContentBlockBase).toBe(true)
})
it('allows instanceof checks for all block types', () => {
const blocks = [
new TextBlock('test'),
new ToolUseBlock({ name: 'tool', toolUseId: '1', input: {} }),
new ImageBlock({ format: 'png', source: { bytes: new Uint8Array() } }),
// ... etc for all block types
]
blocks.forEach(block => {
expect(block instanceof ContentBlockBase).toBe(true)
})
})
it('rejects non-ContentBlock objects', () => {
const notABlock = { type: 'something', data: 'test' }
expect(notABlock instanceof ContentBlockBase).toBe(false)
})
})Documentation Requirements
- Add TSDoc documentation to
ContentBlockBaseclass - Include
@exampleshowing instanceof usage - Document the relationship between
ContentBlockBaseandContentBlocktype union - Update any existing documentation that references content block type checking patterns
Acceptance Criteria
-
ContentBlockBaseabstract class is created with abstracttypeproperty - All 9 content block classes extend
ContentBlockBase - All existing tests pass (backward compatibility verified)
- New tests verify instanceof checks work for all block types
-
ContentBlockBaseis exported from main SDK entry point - TSDoc documentation is complete with examples
- Type checking passes (
npm run type-check) - Linting passes (
npm run lint) - Test coverage maintained at 80%+
- No breaking changes to public API
Files to Modify
src/types/messages.ts- Add base class, update 7 block classessrc/types/media.ts- Update 3 media block classes to extend basesrc/types/__tests__/messages.test.ts- Add tests for instanceof checkssrc/types/__tests__/media.test.ts- Add tests for media block instanceof checkssrc/index.ts- ExportContentBlockBase
Technical Notes
- TypeScript allows a subclass with
readonly type = 'textBlock' as constto satisfy an abstracttype: stringproperty - This is a non-breaking change because it only adds functionality, doesn't remove or change existing APIs
- The
ContentBlocktype union remains the primary type for type annotations ContentBlockBaseis used specifically for runtime instanceof checks
Metadata
Metadata
Assignees
Labels
No labels