← TikTok Interview Insights

TikTok·Software Engineer·Technical Phone Screen·Intermediate

IntermediatePrefer not to say
May 2026

Summary

TikTok software engineer interview with two JavaScript-heavy coding problems back to back. Nothing too exotic but the Promise.all one took more thought than I expected.

Questions Asked (2)

Q1

Write a function that flattens a nested JavaScript object into a single-level object where nested keys are represented as dot-separated paths (e.g., {a: {b: 1}} becomes {'a.b': 1}).

Algorithms & Data StructuresTechnical Trade-offs
Author's notes

Pretty standard once you see it a few times.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying the requirements: discuss handling of arrays, null, undefined, and empty objects. Then, present a recursive solution that builds the path as it traverses the object, and finally analyze time and space complexity and potential trade-offs with iterative approaches.

Pro tip: Mention that you would use a delimiter that is unlikely to appear in keys (e.g., a dot) and discuss how to handle collisions if keys already contain dots. Also, consider using an iterative stack-based approach to avoid stack overflow for deeply nested objects.

1. Clarify requirements and edge cases

Ask about handling arrays, null, undefined, empty objects, and keys containing dots. Confirm the expected output format and whether the original object should be mutated.

2. Choose an approach

Decide between recursive and iterative (stack-based) solutions. Discuss the trade-offs: recursion is simpler but may cause stack overflow; iteration is more complex but safer for deep nesting.

3. Implement the solution

Write clean code that traverses the object, building the path for each key. For recursion, pass the current path and result object; for iteration, use a stack of [object, path] pairs.

4. Test with examples

Walk through test cases: simple nested object, arrays, empty objects, null values, and keys with dots. Verify that the output matches expectations.

5. Analyze complexity and trade-offs

State that time complexity is O(n) where n is the total number of keys, and space complexity is O(n) for the output. Discuss potential improvements or alternative approaches.

Key Points to Mention

  • Handling of arrays: should they be flattened with indices (e.g., 'a.0.b') or treated as leaf values?
  • Treatment of null and undefined: should they be included as values or skipped?
  • Empty objects: should they produce an empty path or be omitted?
  • Keys containing dots: potential ambiguity and how to handle (e.g., escaping or using a different delimiter).
  • Recursive vs iterative approach: stack overflow risk vs code simplicity.
  • Time and space complexity: O(n) time and O(n) space, where n is the number of keys in the flattened object.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.

Q2

Implement Promise.all from scratch. It should accept an iterable of promises or plain values and return a promise that resolves with all results in order, or rejects immediately if any input rejects.

Algorithms & Data StructuresTechnical Trade-offsAPI & Integrations
Author's notes

This one tripped me up more than I'd like to admit.

Create a free account to read the full note

AI HintsAI Generated

Suggested Approach

Start by clarifying requirements and edge cases, then outline the algorithm: iterate over inputs, wrap each in Promise.resolve, track completion count, and resolve when all are done. Write clean code with proper error handling and discuss trade-offs like concurrency and ordering.

Pro tip: Mention that native Promise.all uses a counter and resolves only when all promises settle, and that it rejects immediately on first rejection but other promises continue executing. Also note that non-promise values are resolved as-is.

1. Clarify requirements and edge cases

Ask about input types (iterable, promises, plain values), handling of empty iterable, and whether rejection should cancel other promises. Confirm that order must be preserved.

2. Outline the algorithm

Explain that you'll convert the iterable to an array, create a results array, and use a counter to track resolved promises. For each input, wrap it in Promise.resolve and attach then/catch handlers.

3. Implement the solution

Write code that returns a new Promise. Inside, handle empty input by resolving immediately. For each item, on fulfillment store the value at the correct index and increment the counter; when counter equals length, resolve with results. On rejection, reject the outer promise.

4. Test and discuss edge cases

Walk through examples: all resolve, one rejects, mixed plain values and promises, empty array, and non-array iterables. Mention that other promises continue but their results are ignored after rejection.

5. Discuss trade-offs and optimizations

Talk about concurrency (all start immediately), memory usage (storing all results), and potential improvements like limiting concurrency or using async/await for readability.

Key Points to Mention

  • Use Promise.resolve to handle both promises and plain values uniformly.
  • Maintain order by storing results at the original index.
  • Use a counter to track how many promises have resolved.
  • Reject immediately on first rejection, but other promises continue executing.
  • Handle empty iterable by resolving with an empty array.
  • Consider using async/await for a more concise implementation, but note that it may not preserve order if not careful.

AI-generated suggestions, not part of the candidate's original notes. May be inaccurate — verify before relying on them.