If you wanted to check just one string value, that would be pretty simple.
type ContainsOneString<T extends string> = `${string}${T}${string}`
const tOneA: ContainsOneString<'cat'> = "i pet a cat" // pass
const tOneB: ContainsOneString<'cat'> = "i pet a dog" // error
This is a template literal type where the ${string}'s act like wild cards, and ${T} is the required substring that must be preset.
Playground
Extending that to two strings is trickier, mainly because you don't know the order.
To get around that you can use a union type, where T before U is one member, and U before T is the other member:
type TwoStrings<T extends string, U extends string> =
`${string}${T}${string}${U}${string}`
type ContainsTwoStrings<T extends string, U extends string> =
TwoStrings<T, U> | TwoStrings<U, T>
const t1: ContainsTwoStrings<'apple', 'banana'> = 'xyz apple banana' // pass
const t2: ContainsTwoStrings<'banana', 'cat'> = 'banana cat abc' // pass
const t3: ContainsTwoStrings<'apple', 'banana'> = 'abc xyz def' // error, as not contain 'apple' and 'banana'
Here TwoStrings is a helper type that defines a string where one substring is first, and the other is second. Then ContainsTwoStrings is a union of the T then U case, and the U then T case.
Playground