Willems began his career with amateur side Spartaan '20 from whom he joined Sparta Rotterdam. During his time with Sparta he progressed through the club's youth academy and made his senior debut on 16 January2011, in a match against Go Ahead Eagles. He made 16 appearances in the Dutch second division.
PSV
On 31 August 2011, Willems joined PSV Eindhoven on a three-year contract. He received the number 43 jersey and made his PSV debut on 23 October in a match against Vitesse. Willems became the youngest Dutchman to play in a UEFA competition when he started against Hapoel Tel Aviv on 3 November in a UEFA Europa Leaguegroup stage match. That same month, he was permanently promoted to the first team squad. In December, Willems was targeted for a move to Manchester United, with then United manager Sir Alex Ferguson looking for "the next Patrice Evra". On 3 April 2012, Willems' contract was upgraded and extended until 2016. Willems scored his first professional – and PSV – goal on 22 April 2012 in a match against NEC. With this goal, he became the youngest goalscorer in the 2011–12 Eredivisie. He experienced a great amount of playing time in the 2011–12 season because full-back Erik Pieters was injured. Although being young and quite inexperienced, Willems quickly showed evidence of his raw talent, especially his technique and attacking traits. On 15 July 2015, Willems suffered a serious injury and missed the first half of the 2015–16 season.
On 2 August 2019, Willems joined Newcastle United of the Premier League on a season-long loan deal with an option to buy. Willems scored his first goal for Newcastle and in the Premier League on 14 September, putting the Magpies into a shock lead at reigning UEFA Champions League winnersLiverpool but the side eventually fell to a 1–3 defeat. Willems then scored in a 2–2 draw with reigning league champions Manchester City on 30 November. He was an ever present in the Newcastle side during the first-half of the season but suffered a season ending injury in January 2020 and left the club when his loan expired on 1 July 2020.
International career
In 2011, Willems won the 2011 UEFA European Under-17 Championship with the Netherlands under-17 team. While being selected for the under-19 squad, on 7 May 2012 Willems was named in the provisional list of 36 players for UEFA Euro 2012, one of nine uncapped players to be chosen by senior team manager Bert van Marwijk as part of the preliminary squad. He was still in the Oranje squad for Euro 2012 after Van Marwijk had made a first cut to 27 players on 15 May 2012. Willems also made the final cut into the 23-man squad, being given the number 15 shirt. He made his first unofficial appearance for the senior national team on 22 May 2012 in a friendly match against Bayern Munich. On 26 May 2012, Willems made his first appearance with the senior Dutch side in a match against Bulgaria. At the Euro 2012, Willems made his first start for the Netherlands, against Denmark, becoming the youngest ever player to play at the Euros and the fourth-youngest player to play for the Netherlands, at 18 years and 71 days of age. The record was previously held by Belgian Enzo Scifo, at 18 years and 115 days. He featured in all the group stage games, however the Netherlands were eliminated from the tournament after losing all three group stage matches.