Migrates TypeScript projects to strict mode incrementally with type guards, utility types, and best practices. Use when users request "TypeScript strict", "strict mode migration", "type safety", "strict TypeScript", or "ts-strict".
Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.
Quelldateien prüfen
Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.
Mit Codex oder Claude installieren Kopieren Sie diesen Prompt, fügen Sie ihn in Codex, Claude oder einen anderen Assistant ein und lassen Sie die Skill-Seite prüfen und installieren.
Ein direkter Befehl überspringt den Prüf-Prompt. Prüfen Sie die Quelle, bevor Sie ihn ausführen.
Migrates TypeScript projects to strict mode incrementally with type guards, utility types, and best practices. Use when users request "TypeScript strict", "strict mode migration", "type safety", "strict TypeScript", or "ts-strict".
TypeScript Strict Migrator
Incrementally migrate to TypeScript strict mode for maximum type safety.
Core Workflow
Audit current state: Check existing type errors
Enable incrementally: One flag at a time
Fix errors: Systematic approach per flag
Add type guards: Runtime type checking
Use utility types: Proper type transformations
Document patterns: Team guidelines
Strict Mode Flags
// tsconfig.json - Full strict mode{"compilerOptions":{// Master flag (enables all below)"strict":true,// Individual flags (enabled by strict)"noImplicitAny":true,"strictNullChecks":true,
// Type guard functionsfunctionisString(value: unknown): value is string {
returntypeof value === 'string';
}
functionisNumber(value: unknown): value is number {
returntypeof value === 'number';
}
functionisObject(value: unknown): value is Record<string, unknown> {
returntypeof value === 'object' && value !== null;
}
function isArray<T>(value: unknown, itemGuard: (item: unknown) => item is T): value is T[] {
returnArray.isArray(value) && value.every(itemGuard);
}
// UsagefunctionprocessInput(input: unknown) {
if (isString(input)) {
return input.toUpperCase(); // input is string
}
if (isNumber(input)) {
return input.toFixed(2); // input is number
}
thrownewError('Invalid input type');
}
Object Type Guards
interfaceUser {
id: string;
name: string;
email: string;
role: 'admin' | 'user';
}
interfaceApiResponse<T> {
data: T;
success: boolean;
}
// Type guard for UserfunctionisUser(value: unknown): value is User {
return (
isObject(value) &&
typeof value.id === 'string' &&
typeof value.name === 'string' &&
typeof value.email === 'string' &&
(value.role === 'admin' || value.role === 'user')
);
}
// Type guard for API responsefunction isApiResponse<T>(
value: unknown,
dataGuard: (data: unknown) => data is T
): value is ApiResponse<T> {
return (
isObject(value) &&
typeof value.success === 'boolean' &&
'data'in value &&
dataGuard(value.data)
);
}
// UsageasyncfunctionfetchUser(id: string): Promise<User> {
const response = awaitfetch(`/api/users/${id}`);
constdata: unknown = await response.json();
if (!isApiResponse(data, isUser)) {
thrownewError('Invalid API response');
}
return data.data;
}
Discriminated Unions
// Discriminated union patterntypeResult<T, E = Error> =
| { success: true; data: T }
| { success: false; error: E };
function createSuccess<T>(data: T): Result<T> {
return { success: true, data };
}
function createError<E = Error>(error: E): Result<never, E> {
return { success: false, error };
}
// Type guard via discriminantfunction isSuccess<T, E>(result: Result<T, E>): result is { success: true; data: T } {
return result.success === true;
}
// UsageasyncfunctionprocessRequest(): Promise<Result<User>> {
try {
const user = awaitfetchUser('123');
returncreateSuccess(user);
} catch (error) {
returncreateError(error instanceofError ? error : newError(String(error)));
}
}
const result = awaitprocessRequest();
if (isSuccess(result)) {
console.log(result.data.name); // TypeScript knows data exists
} else {
console.error(result.error.message); // TypeScript knows error exists
}
Utility Types for Migration
// Making properties requiredtypeRequiredUser = Required<User>;
// Making properties optionaltypePartialUser = Partial<User>;
// Pick specific propertiestypeUserCredentials = Pick<User, 'email' | 'id'>;
// Omit specific propertiestypePublicUser = Omit<User, 'password' | 'internalId'>;
// Make properties readonlytypeReadonlyUser = Readonly<User>;
// Deep readonlytypeDeepReadonly<T> = {
readonly [P in keyof T]: T[P] extendsobject
? DeepReadonly<T[P]>
: T[P];
};
// NonNullabletypeDefiniteString = NonNullable<string | null | undefined>; // string// Extract and ExcludetypeAdminRole = Extract<User['role'], 'admin'>; // 'admin'typeNonAdminRole = Exclude<User['role'], 'admin'>; // 'user'// Record typetypeUserById = Record<string, User>;
// Parameters and ReturnTypetypeFetchParams = Parameters<typeof fetch>; // [input: RequestInfo, init?: RequestInit]typeFetchReturn = ReturnType<typeof fetch>; // Promise<Response>
Common Migration Patterns
Handling Optional Chaining
// Before: unsafe accessconst userName = user.profile.settings.displayName;
// After: safe access with optional chainingconst userName = user?.profile?.settings?.displayName;
// With nullish coalescingconst userName = user?.profile?.settings?.displayName ?? 'Anonymous';
// With type narrowingfunctiongetDisplayName(user: User | null): string {
if (!user?.profile?.settings?.displayName) {
return'Anonymous';
}
return user.profile.settings.displayName;
}
Assertion Functions
// Assertion functionfunction assertIsDefined<T>(value: T): asserts value is NonNullable<T> {
if (value === undefined || value === null) {
thrownewError('Value is not defined');
}
}
functionassertIsUser(value: unknown): asserts value is User {
if (!isUser(value)) {
thrownewError('Value is not a User');
}
}
// UsagefunctionprocessUser(maybeUser: unknown) {
assertIsUser(maybeUser);
// maybeUser is now Userconsole.log(maybeUser.name);
}
// Before: unsafe index accessconstusers: Record<string, User> = {};
const user = users['unknown-id'];
console.log(user.name); // Error with noUncheckedIndexedAccess// After: proper null checkconst user = users['unknown-id'];
if (user) {
console.log(user.name);
}
// Or with assertionconst user = users['known-id']!; // Only if you're certain// Better: use Mapconst usersMap = newMap<string, User>();
const user = usersMap.get('some-id'); // User | undefined by design